6_1.ts 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import { ExtractNumbers, LoadInput } from "../common.ts";
  2. const tests = [
  3. "Time: 7 15 30",
  4. "Distance: 9 40 200",
  5. ];
  6. const input = await LoadInput(6);
  7. const races = ParseRaces(input);
  8. races.forEach((race) => FindWinningTimes(race));
  9. // Get our output as a "checksum"
  10. // The checksum is the number of ways each race could be won multiplied by each other
  11. console.log("The race checksum is", races.reduce((accumulator, race) => accumulator *= race.WinningTimes.length, 1));
  12. /**
  13. * Parse the input to get a list of races
  14. *
  15. * @param {string[]} inputLines The two lines of input
  16. * @returns {Race[]} A list of race details
  17. */
  18. function ParseRaces(inputLines: string[]): Race[] {
  19. const races: Race[] = [];
  20. const times = ExtractNumbers(inputLines.shift() || "");
  21. const distances = ExtractNumbers(inputLines.shift() || "");
  22. do {
  23. races.push({
  24. Duration: times.shift() || -1,
  25. RecordDistance: distances.shift() || -1,
  26. WinningTimes: [],
  27. });
  28. } while (times.length);
  29. return races;
  30. }
  31. /**
  32. * Find all possible winning times for a given race
  33. *
  34. * @param {Race} race The race to find winning times for
  35. */
  36. function FindWinningTimes(race: Race) {
  37. // For our sake, flip the sign on the RecordDistance to create a floor for the parabola
  38. let [lowerBounds, upperBounds] = FindQuadraticRoots(-1, race.Duration, (race.RecordDistance * -1));
  39. // Exclusively bind the two bounds to integers
  40. // Add/subtract 0.01 to force integer roots to their next whole number
  41. lowerBounds = Math.ceil(lowerBounds + 0.01);
  42. upperBounds = Math.floor(upperBounds - 0.01);
  43. for(let i = lowerBounds; i <= upperBounds; i++) { race.WinningTimes.push(i); }
  44. }
  45. /**
  46. * Find the quadratic roots of a parabola
  47. *
  48. * @param a
  49. * @param b
  50. * @param c
  51. * @returns The quadratic roots of a parabola
  52. */
  53. function FindQuadraticRoots(a: number, b: number, c: number): number[] {
  54. if (a == 0) { return []; }
  55. // Solve for the discriminant -- sqrt(b^2 - 4ac)
  56. const discriminant = Math.sqrt(Math.pow(b, 2) - (4 * a * c));
  57. return [
  58. ((b * -1) + discriminant) / (2 * a),
  59. ((b * -1) - discriminant) / (2 * a),
  60. ];
  61. }
  62. /**
  63. * Information regarding a boat race
  64. */
  65. type Race = {
  66. /** The total duration of the race in milliseconds */
  67. Duration: number,
  68. /** The current record holder for boat distance */
  69. RecordDistance: number,
  70. /** A list of times the boat's button could be held that would beat the RecordDistance */
  71. WinningTimes: number[]
  72. };