diff --git a/solutions/typescript/2018/10/package.json b/solutions/typescript/2018/10/package.json index 47a632ba4..bd225f7da 100644 --- a/solutions/typescript/2018/10/package.json +++ b/solutions/typescript/2018/10/package.json @@ -45,11 +45,6 @@ "p2": "RUN=1 NODE_NO_WARNINGS=1 ts-node-esm src/p2.ts" }, "exports": { - "./boundary.interface": { - "types": "./src/boundary.interface.ts", - "import": "./dist/boundary.interface.js", - "default": "./dist/boundary.interface.js" - }, "./interpreter.function": { "types": "./src/interpreter.function.ts", "import": "./dist/interpreter.function.js", diff --git a/solutions/typescript/2018/10/src/boundary.interface.ts b/solutions/typescript/2018/10/src/boundary.interface.ts deleted file mode 100644 index 34c1d1797..000000000 --- a/solutions/typescript/2018/10/src/boundary.interface.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface Boundary { - maxX: number; - minX: number; - maxY: number; - minY: number; -} diff --git a/solutions/typescript/2018/10/src/interpreter.function.ts b/solutions/typescript/2018/10/src/interpreter.function.ts index bb4e9b9ca..0db357049 100644 --- a/solutions/typescript/2018/10/src/interpreter.function.ts +++ b/solutions/typescript/2018/10/src/interpreter.function.ts @@ -1,5 +1,5 @@ import { split } from '@alexaegis/advent-of-code-lib'; -import { Vector } from './model/vector.class.js'; +import { MotionVector } from './model/motion-vector.class.js'; -export const interpreter = (input: string): Vector[] => - split(input).map((line) => Vector.parse(line)); +export const interpreter = (input: string): MotionVector[] => + split(input).map((line) => MotionVector.parse(line)); diff --git a/solutions/typescript/2018/10/src/model/coord.class.ts b/solutions/typescript/2018/10/src/model/coord.class.ts deleted file mode 100644 index dfe034fee..000000000 --- a/solutions/typescript/2018/10/src/model/coord.class.ts +++ /dev/null @@ -1,27 +0,0 @@ -export class Coord { - public constructor( - public x: number, - public y: number, - ) {} - - static parse(input: string): Coord { - const split = input.split(','); - return new Coord(Number(split[0]), Number(split[1])); - } - - public add(coord: Coord): this { - this.x += coord.x; - this.y += coord.y; - return this; - } - - public sub(coord: Coord): this { - this.x -= coord.x; - this.y -= coord.y; - return this; - } - - public toString(): string { - return `${this.x},${this.y}`; - } -} diff --git a/solutions/typescript/2018/10/src/model/motion-vector.class.ts b/solutions/typescript/2018/10/src/model/motion-vector.class.ts new file mode 100644 index 000000000..5c257e383 --- /dev/null +++ b/solutions/typescript/2018/10/src/model/motion-vector.class.ts @@ -0,0 +1,23 @@ +import { Vec2, type Vec2String } from '@alexaegis/advent-of-code-lib'; +import { type } from 'arktype'; + +export class MotionVector { + static inputType = type(['string', 'string', 'string', 'string', 'string']); + public constructor( + public position: Vec2, + public velocity: Vec2, + ) {} + + static parse(input: string): MotionVector { + const split = MotionVector.inputType.assert(input.split(/[<>]/)); + return new MotionVector(new Vec2(split[1] as Vec2String), new Vec2(split[3] as Vec2String)); + } + + public move(): Vec2 { + return this.position.addMut(this.velocity); + } + + public toString(): string { + return `<${this.position.toString()}> , <${this.velocity.toString()}>`; + } +} diff --git a/solutions/typescript/2018/10/src/model/vector.class.ts b/solutions/typescript/2018/10/src/model/vector.class.ts deleted file mode 100644 index 963455f29..000000000 --- a/solutions/typescript/2018/10/src/model/vector.class.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { type } from 'arktype'; -import { Coord } from './coord.class.js'; -export class Vector { - static inputType = type(['string', 'string', 'string', 'string', 'string']); - public constructor( - public position: Coord, - public velocity: Coord, - ) {} - - static parse(input: string): Vector { - const split = Vector.inputType.assert(input.split(/[<>]/)); - return new Vector(Coord.parse(split[1]), Coord.parse(split[3])); - } - - public move(): Coord { - return this.position.add(this.velocity); - } - - public toString(): string { - return `<${this.position.toString()}> , <${this.velocity.toString()}>`; - } -} diff --git a/solutions/typescript/2018/10/src/p1.ts b/solutions/typescript/2018/10/src/p1.ts index 0f4841b05..dd50a2b8b 100644 --- a/solutions/typescript/2018/10/src/p1.ts +++ b/solutions/typescript/2018/10/src/p1.ts @@ -1,43 +1,26 @@ -import { task } from '@alexaegis/advent-of-code-lib'; -import { max, min } from '@alexaegis/advent-of-code-lib/math'; +import { BoundingBox, Vec2, task } from '@alexaegis/advent-of-code-lib'; import packageJson from '../package.json'; -import type { Boundary } from './boundary.interface.js'; import { interpreter } from './interpreter.function.js'; -import { Coord } from './model/coord.class.js'; -import type { Vector } from './model/vector.class.js'; -export const normalize = (input: Vector[]): Vector[] => { - const { minX, minY } = boundary(input); - const norm = new Coord(minX, minY); +import type { MotionVector } from './model/motion-vector.class.js'; + +export const normalize = (input: MotionVector[]): MotionVector[] => { + const aabb = BoundingBox.fromVectors(input.map((i) => i.position)); return input.map((vector) => { - vector.position.sub(norm); + vector.position.subMut(aabb.size); return vector; }); }; -export const area = (b: Boundary): number => (b.maxX - b.minX) * (b.maxY - b.minY); // did not terminate correctly -export const verticalArea = (b: Boundary): number => b.maxY - b.minY; - -export const boundary = (input: Vector[]): Boundary => { - return { - maxX: input.map((vector) => vector.position.x).reduce(max), - minX: input.map((vector) => vector.position.x).reduce(min), - maxY: input.map((vector) => vector.position.y).reduce(max), - minY: input.map((vector) => vector.position.y).reduce(min), - }; -}; - -export const print = (input: Vector[]): string => { - const { maxX, minX, maxY, minY } = boundary(input); - console.log(`maxX: ${maxX}, minX: ${minX}, maxY: ${maxY}, minY: ${minY}`); - +export const print = (input: MotionVector[]): string => { + const aabb = BoundingBox.fromVectors(input.map((i) => i.position)); const stars = new Set(input.map((vector) => vector.position.toString())); let pic = ''; - for (let y = minY; y <= maxY; y++) { + for (let y = aabb.top; y <= aabb.bottom; y++) { let row = ''; - for (let x = minX; x <= maxX; x++) { - row = row + stars.has(new Coord(x, y).toString()) ? '#' : '.'; + for (let x = aabb.left; x <= aabb.right; x++) { + row = row + stars.has(new Vec2(x, y).toString()) ? '#' : '.'; } pic = pic + row + '\n'; } @@ -46,13 +29,15 @@ export const print = (input: Vector[]): string => { export const p1 = (input: string): number => { const vectors = interpreter(input); - let minArea: number = area(boundary(vectors)); + const aabb = BoundingBox.fromVectors(vectors.map((i) => i.position)); + let minArea: number = aabb.area(); let i = 0; for (;;) { for (const vector of vectors) { - vector.position.add(vector.velocity); + vector.position.addMut(vector.velocity); } - const currArea = verticalArea(boundary(vectors)); + const aabb = BoundingBox.fromVectors(vectors.map((i) => i.position)); + const currArea = aabb.vertical.length; if (minArea > currArea) { minArea = currArea; } else break; diff --git a/solutions/typescript/libs/lib/src/model/vector/bounding-box.class.ts b/solutions/typescript/libs/lib/src/model/vector/bounding-box.class.ts index 1176fdd4b..26e839956 100644 --- a/solutions/typescript/libs/lib/src/model/vector/bounding-box.class.ts +++ b/solutions/typescript/libs/lib/src/model/vector/bounding-box.class.ts @@ -5,8 +5,6 @@ import type { Vec2Like } from './vec2.class.types.js'; export type BoundingBoxCorner = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight'; /** - * TODO: Rename to Area - * * It consists of two closed intervals from left to right and bottom to top * * It uses a screen coordinate system where 0,0 is at the top left, and Y @@ -176,6 +174,10 @@ export class BoundingBox { } } + area(): number { + return this.horizontal.length * this.vertical.length; + } + forEach(callback: (x: number, y: number) => void, resolution = 1): void { if (this.isFinite()) { for (let y = this.top; y <= this.bottom; y += resolution) {