Browse Source

Add day 6 part i solution

ApisNecros 1 year ago
parent
commit
0a0f079f44
1 changed files with 89 additions and 0 deletions
  1. 89 0
      6/6_1.ts

+ 89 - 0
6/6_1.ts

@@ -0,0 +1,89 @@
+import { ExtractNumbers, LoadInput } from "../common.ts";
+
+const tests = [
+    "Time:      7  15   30",
+    "Distance:  9  40  200",
+];
+
+const input = await LoadInput(6);
+
+const races = ParseRaces(input);
+
+races.forEach((race) => FindWinningTimes(race));
+
+// Get our output as a "checksum"
+// The checksum is the number of ways each race could be won multiplied by each other
+console.log("The race checksum is", races.reduce((accumulator, race) => accumulator *= race.WinningTimes.length, 1));
+
+
+/**
+ * Parse the input to get a list of races
+ *
+ * @param {string[]} inputLines The two lines of input
+ * @returns {Race[]} A list of race details
+ */
+function ParseRaces(inputLines: string[]): Race[] {
+    const races: Race[] = [];
+
+    const times = ExtractNumbers(inputLines.shift() || "");
+    const distances = ExtractNumbers(inputLines.shift() || "");
+
+    do {
+        races.push({
+            Duration: times.shift() || -1,
+            RecordDistance: distances.shift() || -1,
+            WinningTimes: [],
+        });
+    } while (times.length);
+
+    return races;
+}
+
+/**
+ * Find all possible winning times for a given race
+ *
+ * @param {Race} race The race to find winning times for
+ */
+function FindWinningTimes(race: Race) {
+    // For our sake, flip the sign on the RecordDistance to create a floor for the parabola
+    let [lowerBounds, upperBounds] = FindQuadraticRoots(-1, race.Duration, (race.RecordDistance * -1));
+
+    // Exclusively bind the two bounds to integers
+    // Add/subtract 0.01 to force integer roots to their next whole number
+    lowerBounds = Math.ceil(lowerBounds + 0.01);
+    upperBounds = Math.floor(upperBounds - 0.01);
+
+    for(let i = lowerBounds; i <= upperBounds; i++) { race.WinningTimes.push(i); }
+}
+
+/**
+ * Find the quadratic roots of a parabola
+ *
+ * @param a 
+ * @param b 
+ * @param c 
+ * @returns The quadratic roots of a parabola
+ */
+function FindQuadraticRoots(a: number, b: number, c: number): number[] {
+    if (a == 0) { return []; }
+
+    // Solve for the discriminant -- sqrt(b^2 - 4ac)
+    const discriminant = Math.sqrt(Math.pow(b, 2) - (4 * a * c));
+    
+    return [
+        ((b * -1) + discriminant) / (2 * a),
+        ((b * -1) - discriminant) / (2 * a),
+    ];
+}
+
+/**
+ * Information regarding a boat race
+ */
+type Race = {
+    /** The total duration of the race in milliseconds */
+    Duration: number,
+    /** The current record holder for boat distance */
+    RecordDistance: number,
+    /** A list of times the boat's button could be held that would beat the RecordDistance */
+    WinningTimes: number[]
+};