import { filter, isOutOfBound, map, mapWithIndex, reduce } from "fp-ts/lib/Array"; import { pipe } from "fp-ts/lib/function"; import { startsWith } from "fp-ts/lib/string"; import { diagnostics } from "./input"; import { diagnostics as testDiagnostics } from "./input.test"; type Stat = { ones: number, zeros: number }; const bitStats = (as: string[]): Stat[] => pipe( as, reduce( [] as Stat[], (acc, bits) => pipe( [...bits], mapWithIndex((i, b) => ({ ones: b === "1" ? (acc[i]?.ones ?? 0) + 1 : (acc[i]?.ones ?? 0), zeros: b=== "0" ? (acc[i]?.zeros ?? 0) + 1 : (acc[i]?.zeros ?? 0) })) ) ) ); const mostCommonBits = (as: Stat[]) => pipe( as, map(({ ones, zeros }) => ones < zeros ? "0" : "1") ); const leastCommonBits = (as: Stat[]) => pipe( as, map(({ ones, zeros }) => ones < zeros ? "1" : "0") ); const diagBitStats = pipe( diagnostics, bitStats ); const gamma = pipe(diagBitStats, mostCommonBits).join(""); const epsilon = pipe(diagBitStats, leastCommonBits).join(""); console.log("gamma rate is ", gamma); console.log("epsilon rate is", epsilon); console.log("power consumption is", parseInt(gamma, 2) * parseInt(epsilon, 2)); const calculator = (evaluate: typeof mostCommonBits) => (diagNumbers: string[]) => { const iterator = (as: string[], currFilter: string): string => { const filteredDiagNumbers = pipe(as, filter(startsWith(currFilter))); if (isOutOfBound(1, filteredDiagNumbers)) { return filteredDiagNumbers[0]; } const newFilterChar = pipe(filteredDiagNumbers, bitStats, evaluate)[currFilter.length]; return iterator(filteredDiagNumbers, currFilter + newFilterChar); } return iterator(diagNumbers, ""); }; const oxygenRatingCalculator = calculator(mostCommonBits); const co2RatingCalculator = calculator(leastCommonBits); const oxygenRating = pipe(diagnostics, oxygenRatingCalculator); const co2Rating = pipe(diagnostics, co2RatingCalculator); console.log("oxygen generator rating is", oxygenRating); console.log("CO2 scrubber rating is", co2Rating); console.log("life support rating is", parseInt(oxygenRating, 2) * parseInt(co2Rating, 2));