import {anyCharOf, spaces1, string, whitespace} from "parjs"; import {between, exactly, manySepBy, stringify, then} from "parjs/combinators"; import {Range} from "immutable"; import fs from "fs"; export type Race = [number, number]; const timeName = string('Time:').pipe(then(spaces1())); const distanceName = string('Distance:').pipe(then(spaces1())); const timeParser = anyCharOf("0123456789").pipe(manySepBy(whitespace().pipe(exactly(2))), stringify(), between(timeName, whitespace())); const distanceParser = anyCharOf("0123456789").pipe(manySepBy(whitespace().pipe(exactly(2))), stringify(), between(distanceName, whitespace())); const parser = timeParser.pipe(then(distanceParser)); export class BoatRace { private readonly race: Race; constructor(input: string) { const [times, distances] = parser.parse(input).value; this.race = [parseInt(times), parseInt(distances)]; } numberOfWinningMethods = (race: Race): number => { const [time, distance] = race; const canWin = (holdingTime: number) => ((time - holdingTime) * holdingTime) > distance; const range = Range(0, time).filter(canWin).cacheResult(); return range.size || 0; } public totalNumberOfWaysToBeatRace(): number { return this.numberOfWinningMethods(this.race); } } export const runDaySix = () => { const input = fs.readFileSync('./inputs/day_six_input.txt', 'utf-8').trimEnd(); const races = new BoatRace(input); console.log(races.totalNumberOfWaysToBeatRace()); }