day05.ts 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import * as A from "fp-ts/Array";
  2. import * as N from "fp-ts/number";
  3. import * as O from "fp-ts/Option";
  4. import { pipe } from "fp-ts/lib/function";
  5. import { contramap, max, min } from "fp-ts/lib/Ord";
  6. import { Eq, struct } from 'fp-ts/Eq'
  7. import { vectors as testVetctors } from "./input.test";
  8. import { vectors as inputVectors } from "./input";
  9. type Point = { x: number, y: number };
  10. type Vector = { from: Point, to: Point };
  11. const parseVectors = (input: string) => pipe(
  12. input.split("\n"),
  13. A.map<string, Vector>(v => {
  14. const points = pipe(
  15. v.split(" -> "),
  16. A.map<string, Point>(p => {
  17. const coords = pipe(
  18. p.split(","),
  19. A.map(parseInt)
  20. );
  21. return {
  22. x: coords[0],
  23. y: coords[1]
  24. };
  25. })
  26. );
  27. return {
  28. from: points[0],
  29. to: points[1]
  30. };
  31. })
  32. );
  33. const vectors = parseVectors(
  34. // testVetctors
  35. inputVectors
  36. );
  37. const maxNum = max(N.Ord);
  38. const minNum = min(N.Ord);
  39. const expand = (vector: Vector): Point[] => pipe(
  40. vector.from.x === vector.to.x
  41. ? A.replicate(maxNum(vector.to.y, vector.from.y) - minNum(vector.to.y, vector.from.y) + 1, vector.from.x)
  42. : A.makeBy(
  43. maxNum(vector.to.x, vector.from.x) - minNum(vector.to.x, vector.from.x) + 1,
  44. n => (vector.to.x > vector.from.x ? vector.from.x + n : vector.from.x - n)
  45. ),
  46. A.zip(vector.from.y === vector.to.y
  47. ? A.replicate(maxNum(vector.to.x, vector.from.x) - minNum(vector.to.x, vector.from.x) + 1, vector.from.y)
  48. : A.makeBy(
  49. maxNum(vector.to.y, vector.from.y) - minNum(vector.to.y, vector.from.y) + 1,
  50. n => (vector.to.y > vector.from.y ? vector.from.y + n : vector.from.y - n)
  51. )),
  52. A.map(([x, y]) => ({ x, y }))
  53. );
  54. const byX = pipe(N.Ord, contramap((p: Point) => p.x));
  55. const byY = pipe(N.Ord, contramap((p: Point) => p.y));
  56. const eqPoint: Eq<Point> = struct({
  57. x: N.Eq,
  58. y: N.Eq
  59. });
  60. const group = (points: Point[]): Point[][] => pipe(
  61. points,
  62. A.reduce([] as Point[][], (groupped, p) =>
  63. pipe(groupped,
  64. A.last,
  65. O.chain(A.last),
  66. O.map(pp => eqPoint.equals(pp, p)),
  67. O.getOrElse(() => false))
  68. ? pipe(groupped,
  69. A.init,
  70. O.map(is => [...is, pipe(groupped, A.last, O.map(l => [...l, p]), O.getOrElse(() => [p]))]),
  71. O.getOrElseW(() => pipe(groupped, A.append([p]))))
  72. : pipe(groupped,
  73. A.append([p])))
  74. );
  75. const result = pipe(
  76. vectors,
  77. // A.filter(v => v.from.x === v.to.x || v.from.y === v.to.y),
  78. A.map(expand),
  79. A.flatten,
  80. A.sortBy([byX, byY]),
  81. group,
  82. A.reduce(0, (count, ps) => ps.length > 1 ? count + 1 : count)
  83. );
  84. console.log(result);