| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- import * as A from "fp-ts/Array";
- import * as N from "fp-ts/number";
- 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 : vector.to.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 : vector.to.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[][] => {
- const iterator = (points: Point[], grouppedPoints: Point[][]): Point[][] => {
- if (A.isEmpty(points)) {
- return grouppedPoints;
- }
- const { init, rest } = pipe(points, A.spanLeft(p => eqPoint.equals(points[0], p)));
- return iterator(rest, pipe([init], A.concat(grouppedPoints)))
- }
- return iterator(points, [[]]);
- }
- 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);
|