import * as A from "fp-ts/Array"; import * as S from "fp-ts/string"; import * as RA from "fp-ts/ReadonlyArray"; import * as N from "fp-ts/number"; import { flow, pipe } from "fp-ts/lib/function"; import { concatAll } from "fp-ts/lib/Monoid"; import { fromCompare } from "fp-ts/Ord"; import { signalPatterns as testSignalPatterns } from "./input.test"; import { signalPatterns as inputSignalPatterns } from "./input"; type SignalPatterns = { patterns: string[], digits: string[] }; const parseSignalPatterns = (input: string) => pipe( input.split("\n"), A.map(lines => lines.split(" | ")), A.map(lineParts => pipe(lineParts, A.map(parts => parts.split(" ")))), A.map(([patterns, digits]) => ({ patterns, digits })) ); const signalPatterns = parseSignalPatterns( // testSignalPatterns inputSignalPatterns ); const easyDigitCount = pipe( signalPatterns, A.map(signalPattern => signalPattern.digits), A.flatten, A.reduce(0, (count, digit) => pipe([2, 4, 3, 7], A.some(n => n === digit.length)) ? count + 1 : count) ); console.log(easyDigitCount); type PatternKey = { [pattern: string]: string }; const deductKey = (patterns: string[]): PatternKey => { return pipe( patterns, A.map(p => pipe(p, S.split(""), RA.sort(S.Ord), concatAll(S.Monoid))), A.sort(fromCompare((a: string, b: string) => a.length < b.length ? -1 : a.length > b.length ? 1 : 0)), A.reduce({} as PatternKey, (key, pattern) => { const segmentsOf = (value: string) => pipe( pipe(Object.keys(key), A.filter(k => key[k] === value)), A.map(S.split("")), RA.flatten ); const contains = (segments: readonly string[]) => (pattern: string) => pipe( segments, RA.reduce(true, (res, segment) => res && S.includes(segment)(pattern)) ) switch ((pipe(pattern, S.size))) { case 2: return { ...key, [pattern]: "1" }; case 3: return { ...key, [pattern]: "7" }; case 4: return { ...key, [pattern]: "4" }; case 5: if (pipe(pattern, contains(segmentsOf("1")))) { return { ...key, [pattern]: "3" }; } if (pipe(pattern, contains(pipe(segmentsOf("4"), RA.difference(S.Eq)(segmentsOf("1")))))) { return { ...key, [pattern]: "5"}; } return { ...key, [pattern]: "2" }; case 6: if (pipe(pattern, contains(segmentsOf("4")))) { return { ...key, [pattern]: "9" }; } if (pipe(pattern, contains(segmentsOf("7")))) { return { ...key, [pattern]: "0" }; } return { ...key, [pattern]: "6" }; case 7: return { ...key, [pattern]: "8" }; default: return key; } }) ); } const solveDigit = (key: PatternKey) => (digit: string): string => { return key[pipe(digit, S.split(""), RA.sort(S.Ord), concatAll(S.Monoid))] ?? "X"; } const displayDigits = pipe( signalPatterns, A.map(sp => ({ key: deductKey(sp.patterns), digits: sp.digits })), A.map(({ key, digits }) => pipe(digits, A.map(flow(solveDigit(key))))), A.map(concatAll(S.Monoid)), A.map(parseInt) ); console.log(pipe(displayDigits, concatAll(N.MonoidSum)));