day05.ts 2.7 KB

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