day08.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import * as A from "fp-ts/Array";
  2. import * as S from "fp-ts/string";
  3. import * as RA from "fp-ts/ReadonlyArray";
  4. import * as N from "fp-ts/number";
  5. import { flow, pipe } from "fp-ts/lib/function";
  6. import { concatAll } from "fp-ts/lib/Monoid";
  7. import { fromCompare } from "fp-ts/Ord";
  8. import { signalPatterns as testSignalPatterns } from "./input.test";
  9. import { signalPatterns as inputSignalPatterns } from "./input";
  10. type SignalPatterns = {
  11. patterns: string[],
  12. digits: string[]
  13. };
  14. const parseSignalPatterns = (input: string) => pipe(
  15. input.split("\n"),
  16. A.map(lines => lines.split(" | ")),
  17. A.map(lineParts => pipe(lineParts, A.map(parts => parts.split(" ")))),
  18. A.map(([patterns, digits]) => ({ patterns, digits }))
  19. );
  20. const signalPatterns = parseSignalPatterns(
  21. // testSignalPatterns
  22. inputSignalPatterns
  23. );
  24. const easyDigitCount = pipe(
  25. signalPatterns,
  26. A.map(signalPattern => signalPattern.digits),
  27. A.flatten,
  28. A.reduce(0, (count, digit) => pipe([2, 4, 3, 7], A.some(n => n === digit.length)) ? count + 1 : count)
  29. );
  30. console.log(easyDigitCount);
  31. type PatternKey = { [pattern: string]: string };
  32. const deductKey = (patterns: string[]): PatternKey => {
  33. return pipe(
  34. patterns,
  35. A.map(p => pipe(p, S.split(""), RA.sort(S.Ord), concatAll(S.Monoid))),
  36. A.sort(fromCompare((a: string, b: string) => a.length < b.length ? -1 : a.length > b.length ? 1 : 0)),
  37. A.reduce({} as PatternKey, (key, pattern) => {
  38. const segmentsOf = (value: string) => pipe(
  39. pipe(Object.keys(key), A.filter(k => key[k] === value)),
  40. A.map(S.split("")),
  41. RA.flatten
  42. );
  43. const contains = (segments: readonly string[]) => (pattern: string) => pipe(
  44. segments,
  45. RA.reduce(true, (res, segment) => res && S.includes(segment)(pattern))
  46. )
  47. switch ((pipe(pattern, S.size))) {
  48. case 2:
  49. return { ...key, [pattern]: "1" };
  50. case 3:
  51. return { ...key, [pattern]: "7" };
  52. case 4:
  53. return { ...key, [pattern]: "4" };
  54. case 5:
  55. if (pipe(pattern, contains(segmentsOf("1")))) {
  56. return { ...key, [pattern]: "3" };
  57. }
  58. if (pipe(pattern, contains(pipe(segmentsOf("4"), RA.difference(S.Eq)(segmentsOf("1")))))) {
  59. return { ...key, [pattern]: "5"};
  60. }
  61. return { ...key, [pattern]: "2" };
  62. case 6:
  63. if (pipe(pattern, contains(segmentsOf("4")))) {
  64. return { ...key, [pattern]: "9" };
  65. }
  66. if (pipe(pattern, contains(segmentsOf("7")))) {
  67. return { ...key, [pattern]: "0" };
  68. }
  69. return { ...key, [pattern]: "6" };
  70. case 7:
  71. return { ...key, [pattern]: "8" };
  72. default:
  73. return key;
  74. }
  75. })
  76. );
  77. }
  78. const solveDigit = (key: PatternKey) => (digit: string): string => {
  79. return key[pipe(digit, S.split(""), RA.sort(S.Ord), concatAll(S.Monoid))] ?? "X";
  80. }
  81. const displayDigits = pipe(
  82. signalPatterns,
  83. A.map(sp => ({ key: deductKey(sp.patterns), digits: sp.digits })),
  84. A.map(({ key, digits }) => pipe(digits, A.map(flow(solveDigit(key))))),
  85. A.map(concatAll(S.Monoid)),
  86. A.map(parseInt)
  87. );
  88. console.log(pipe(displayDigits, concatAll(N.MonoidSum)));