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(v => { const points = pipe( v.split(" -> "), A.map(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 = 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);