| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- import * as A from "fp-ts/Array";
- import * as N from "fp-ts/number";
- import * as O from "fp-ts/Option";
- import { pipe } from "fp-ts/lib/function";
- import { contramap, max, min } from "fp-ts/lib/Ord";
- import { Eq, struct } from 'fp-ts/Eq'
- import { vectors as testVetctors } from "./input.test";
- import { vectors as inputVectors } from "./input";
- type Point = { x: number, y: number };
- type Vector = { from: Point, to: Point };
- const parseVectors = (input: string) => pipe(
- input.split("\n"),
- A.map<string, Vector>(v => {
- const points = pipe(
- v.split(" -> "),
- A.map<string, Point>(p => {
- const coords = pipe(
- p.split(","),
- A.map(parseInt)
- );
- return {
- x: coords[0],
- y: coords[1]
- };
- })
- );
- return {
- from: points[0],
- to: points[1]
- };
- })
- );
- const vectors = parseVectors(
- // testVetctors
- inputVectors
- );
- const maxNum = max(N.Ord);
- const minNum = min(N.Ord);
- const expand = (vector: Vector): Point[] => pipe(
- vector.from.x === vector.to.x
- ? A.replicate(maxNum(vector.to.y, vector.from.y) - minNum(vector.to.y, vector.from.y) + 1, vector.from.x)
- : A.makeBy(
- maxNum(vector.to.x, vector.from.x) - minNum(vector.to.x, vector.from.x) + 1,
- n => (vector.to.x > vector.from.x ? vector.from.x + n : vector.from.x - n)
- ),
- A.zip(vector.from.y === vector.to.y
- ? A.replicate(maxNum(vector.to.x, vector.from.x) - minNum(vector.to.x, vector.from.x) + 1, vector.from.y)
- : A.makeBy(
- maxNum(vector.to.y, vector.from.y) - minNum(vector.to.y, vector.from.y) + 1,
- n => (vector.to.y > vector.from.y ? vector.from.y + n : vector.from.y - n)
- )),
- A.map(([x, y]) => ({ x, y }))
- );
- const byX = pipe(N.Ord, contramap((p: Point) => p.x));
- const byY = pipe(N.Ord, contramap((p: Point) => p.y));
- const eqPoint: Eq<Point> = struct({
- x: N.Eq,
- y: N.Eq
- });
- const group = (points: Point[]): Point[][] => pipe(
- points,
- A.reduce([] as Point[][], (groupped, p) =>
- pipe(groupped,
- A.last,
- O.chain(A.last),
- O.map(pp => eqPoint.equals(pp, p)),
- O.getOrElse(() => false))
- ? pipe(groupped,
- A.init,
- O.map(is => [...is, pipe(groupped, A.last, O.map(l => [...l, p]), O.getOrElse(() => [p]))]),
- O.getOrElseW(() => pipe(groupped, A.append([p]))))
- : pipe(groupped,
- A.append([p])))
- );
- const result = pipe(
- vectors,
- // A.filter(v => v.from.x === v.to.x || v.from.y === v.to.y),
- A.map(expand),
- A.flatten,
- A.sortBy([byX, byY]),
- group,
- A.reduce(0, (count, ps) => ps.length > 1 ? count + 1 : count)
- );
- console.log(result);
|