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[] };