From 268b21e68a2591f042878ca580941ea07d1dc973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kleszczy=C5=84ski?= Date: Sun, 15 Dec 2024 20:56:35 +0100 Subject: [PATCH] cleanup --- 2024/d06/index.ts | 63 +++++++++++---------------------------- 2024/d08/index.ts | 34 ++++++++++++++------- 2024/d10/index.ts | 12 ++++---- 2024/d12/index.ts | 39 ++++++++---------------- 2024/d13/index.ts | 18 ++++++----- 2024/d14/index.ts | 22 +++++++------- ts-core/math/direction.ts | 4 +++ ts-core/math/vec2.ts | 34 +++++++++++---------- ts-core/types/Vec2.ts | 4 +-- 9 files changed, 105 insertions(+), 125 deletions(-) diff --git a/2024/d06/index.ts b/2024/d06/index.ts index 1d39bd4..942b755 100644 --- a/2024/d06/index.ts +++ b/2024/d06/index.ts @@ -1,7 +1,7 @@ import { readFileSync } from 'node:fs' import { runExamples, runSolution } from '@magiczne/advent-of-code-ts-core/aoc' -import type { Vec2 } from '@magiczne/advent-of-code-ts-core/types' +import { Direction, Vec2 } from '@magiczne/advent-of-code-ts-core/math' interface Input { map: Array> @@ -11,42 +11,30 @@ interface Input { const rotate = (speed: Vec2): Vec2 => { // From going downwards to going left if (speed.x === 0 && speed.y === 1) { - return { - x: -1, - y: 0, - } + return Direction.left } // From going left to going upwards if (speed.x === -1 && speed.y === 0) { - return { - x: 0, - y: -1, - } + return Direction.up } // From going upwards to going right if (speed.x === 0 && speed.y === -1) { - return { - x: 1, - y: 0, - } + return Direction.right } // From going right to going downwards if (speed.x === 1 && speed.y === 0) { - return { - x: 0, - y: 1, - } + return Direction.down } throw new Error('WTF') } const part1 = (input: Input): number => { - const guardPos: Vec2 = { x: input.guard.x, y: input.guard.y } - const speed: Vec2 = { x: 0, y: -1 } + const guardPos = input.guard.clone() + const speed = Direction.up const visited = new Set() visited.add(`${guardPos.y}_${guardPos.x}`) @@ -57,16 +45,12 @@ const part1 = (input: Input): number => { } if (input.map[guardPos.y + speed.y][guardPos.x + speed.x] === '#') { - const { x, y } = rotate(speed) - - speed.x = x - speed.y = y + speed.updateInPlace(rotate(speed)) continue } - guardPos.x += speed.x - guardPos.y += speed.y + guardPos.addInPlace(speed) visited.add(`${guardPos.y}_${guardPos.x}`) } @@ -74,8 +58,8 @@ const part1 = (input: Input): number => { } const part2 = (input: Input): number => { - const guardPos: Vec2 = { x: input.guard.x, y: input.guard.y } - const speed: Vec2 = { x: 0, y: -1 } + const guardPos = input.guard.clone() + const speed = Direction.up const visited = new Set() visited.add(`${guardPos.y}_${guardPos.x}`) @@ -86,16 +70,12 @@ const part2 = (input: Input): number => { } if (input.map[guardPos.y + speed.y][guardPos.x + speed.x] === '#') { - const { x, y } = rotate(speed) - - speed.x = x - speed.y = y + speed.updateInPlace(rotate(speed)) continue } - guardPos.x += speed.x - guardPos.y += speed.y + guardPos.addInPlace(speed) visited.add(`${guardPos.y}_${guardPos.x}`) } @@ -109,8 +89,8 @@ const part2 = (input: Input): number => { newMap[pathPart[0]][pathPart[1]] = '#' // walk and check cycles - const guardPos: Vec2 = { x: input.guard.x, y: input.guard.y } - const speed: Vec2 = { x: 0, y: -1 } + const guardPos = input.guard.clone() + const speed = Direction.up const visited = new Set() visited.add(`${guardPos.y}_${guardPos.x}_${speed.y}_${speed.x}`) @@ -120,16 +100,12 @@ const part2 = (input: Input): number => { } if (newMap[guardPos.y + speed.y][guardPos.x + speed.x] === '#') { - const { x, y } = rotate(speed) - - speed.x = x - speed.y = y + speed.updateInPlace(rotate(speed)) continue } - guardPos.x += speed.x - guardPos.y += speed.y + guardPos.addInPlace(speed) if (visited.has(`${guardPos.y}_${guardPos.x}_${speed.y}_${speed.x}`)) { cycles++ @@ -164,10 +140,7 @@ const reader = (file: string): Input => { return { map: map as Array>, - guard: { - x: guardX, - y: guardY, - }, + guard: new Vec2({ x: guardX, y: guardY }), } } diff --git a/2024/d08/index.ts b/2024/d08/index.ts index df3e6c7..8a74ecc 100644 --- a/2024/d08/index.ts +++ b/2024/d08/index.ts @@ -2,7 +2,7 @@ import { readFileSync } from 'node:fs' import { runExamples, runSolution } from '@magiczne/advent-of-code-ts-core/aoc' import { combinationsWithoutRepetition } from '@magiczne/advent-of-code-ts-core/combinatorics' -import type { Vec2 } from '@magiczne/advent-of-code-ts-core/types' +import { Vec2 } from '@magiczne/advent-of-code-ts-core/math' type Antenna = Vec2 & { type: 'Antenna'; code: string } type Antinode = { type: 'Antinode'; code: string } @@ -47,18 +47,24 @@ const part1 = (input: Input): number => { const distanceX = Math.abs(firstNode.x - secondNode.x) const distanceY = Math.abs(firstNode.y - secondNode.y) - const secondAntinodeDir: Vec2 = { x: firstNode.x < secondNode.x ? -1 : 1, y: firstNode.y < secondNode.y ? -1 : 1 } - const firstAntinodeDir: Vec2 = { x: firstNode.x < secondNode.x ? 1 : -1, y: firstNode.y < secondNode.y ? 1 : -1 } + const secondAntinodeDir = new Vec2({ + x: firstNode.x < secondNode.x ? -1 : 1, + y: firstNode.y < secondNode.y ? -1 : 1, + }) + const firstAntinodeDir = new Vec2({ + x: firstNode.x < secondNode.x ? 1 : -1, + y: firstNode.y < secondNode.y ? 1 : -1, + }) const antinodes: ReadonlyArray = [ - { + new Vec2({ x: firstNode.x - firstAntinodeDir.x * distanceX, y: firstNode.y - firstAntinodeDir.y * distanceY, - }, - { + }), + new Vec2({ x: secondNode.x - secondAntinodeDir.x * distanceX, y: secondNode.y - secondAntinodeDir.y * distanceY, - }, + }), ] antinodes.forEach(antinode => { @@ -92,8 +98,14 @@ const part2 = (input: Input): number => { const distanceX = Math.abs(firstNode.x - secondNode.x) const distanceY = Math.abs(firstNode.y - secondNode.y) - const secondAntinodeDir: Vec2 = { x: firstNode.x < secondNode.x ? -1 : 1, y: firstNode.y < secondNode.y ? -1 : 1 } - const firstAntinodeDir: Vec2 = { x: firstNode.x < secondNode.x ? 1 : -1, y: firstNode.y < secondNode.y ? 1 : -1 } + const secondAntinodeDir = new Vec2({ + x: firstNode.x < secondNode.x ? -1 : 1, + y: firstNode.y < secondNode.y ? -1 : 1, + }) + const firstAntinodeDir = new Vec2({ + x: firstNode.x < secondNode.x ? 1 : -1, + y: firstNode.y < secondNode.y ? 1 : -1, + }) let antinodes: Array = [] @@ -106,7 +118,7 @@ const part2 = (input: Input): number => { break } - antinodes.push({ x, y }) + antinodes.push(new Vec2({ x, y })) } // Generate antinodes in second direction @@ -118,7 +130,7 @@ const part2 = (input: Input): number => { break } - antinodes.push({ x, y }) + antinodes.push(new Vec2({ x, y })) } antinodes.forEach(antinode => { diff --git a/2024/d10/index.ts b/2024/d10/index.ts index 6b41462..fc590d8 100644 --- a/2024/d10/index.ts +++ b/2024/d10/index.ts @@ -2,7 +2,7 @@ import { readFileSync } from 'node:fs' import { unique } from 'radash' import { runExamples, runSolution } from '@magiczne/advent-of-code-ts-core/aoc' -import type { Vec2 } from '@magiczne/advent-of-code-ts-core/types' +import { Vec2 } from '@magiczne/advent-of-code-ts-core/math' interface Input { map: ReadonlyArray> @@ -12,10 +12,10 @@ interface Input { // Find every neighbor that is larger than one from current position const findIncrementedNeighbors = (map: ReadonlyArray>, position: Vec2): ReadonlyArray => { return [ - { x: position.x, y: position.y - 1 }, - { x: position.x, y: position.y + 1 }, - { x: position.x - 1, y: position.y }, - { x: position.x + 1, y: position.y }, + new Vec2({ x: position.x, y: position.y - 1 }), + new Vec2({ x: position.x, y: position.y + 1 }), + new Vec2({ x: position.x - 1, y: position.y }), + new Vec2({ x: position.x + 1, y: position.y }), ].filter(item => { return map[item.y]?.[item.x] === map[position.y][position.x] + 1 }) @@ -85,7 +85,7 @@ const reader = (file: string): Input => { return acc } - return [...acc, { x, y }] + return [...acc, new Vec2({ x, y })] }, []) }) diff --git a/2024/d12/index.ts b/2024/d12/index.ts index dd18f24..d807ab0 100644 --- a/2024/d12/index.ts +++ b/2024/d12/index.ts @@ -1,8 +1,8 @@ import { readFileSync } from 'node:fs' import { runExamples, runSolution } from '@magiczne/advent-of-code-ts-core/aoc' +import { Direction, Vec2 } from '@magiczne/advent-of-code-ts-core/math' import { ObjectSet } from '@magiczne/advent-of-code-ts-core/structures' -import type { Vec2 } from '@magiczne/advent-of-code-ts-core/types' type Garden = Array> @@ -17,19 +17,9 @@ interface Wall { direction: Vec2 } -const directions: ReadonlyArray = [ - { x: -1, y: 0 }, - { x: 1, y: 0 }, - { x: 0, y: -1 }, - { x: 0, y: 1 }, -] - const neighbors = (pos: Vec2): ReadonlyArray => { - return directions.map(direction => { - return { - x: pos.x + direction.x, - y: pos.y + direction.y, - } + return Direction.cardnial.map(direction => { + return direction.add(pos) }) } @@ -49,11 +39,8 @@ const floodFill = (garden: Garden, position: Vec2) => { if (garden[neighbor.y]?.[neighbor.x] !== crop && !visited.has(neighbor)) { wallSegments.push({ point: pos, - direction: { - // If I had direction here... but i have only neighbors xD - x: neighbor.x - pos.x, - y: neighbor.y - pos.y, - }, + // If I had direction here... but i have only neighbors xD + direction: neighbor.sub(pos), }) } @@ -115,9 +102,9 @@ const floodFill = (garden: Garden, position: Vec2) => { foundWall.end.y = Math.max(foundWall.end.y, wallSegment.point.y) } else { walls.push({ - direction: { ...wallSegment.direction }, - start: { ...wallSegment.point }, - end: { ...wallSegment.point }, + direction: wallSegment.direction.clone(), + start: wallSegment.point.clone(), + end: wallSegment.point.clone(), }) } @@ -142,9 +129,9 @@ const floodFill = (garden: Garden, position: Vec2) => { foundWall.end.x = Math.max(foundWall.end.x, wallSegment.point.x) } else { walls.push({ - direction: { ...wallSegment.direction }, - start: { ...wallSegment.point }, - end: { ...wallSegment.point }, + direction: wallSegment.direction.clone(), + start: wallSegment.point.clone(), + end: wallSegment.point.clone(), }) } @@ -168,7 +155,7 @@ const part1 = (data: Garden): number => { for (let y = 0; y < floodedGarden.length; y++) { for (let x = 0; x < floodedGarden.length; x++) { if (floodedGarden[y][x] !== '.') { - const floodedRegion = floodFill(floodedGarden, { x, y }) + const floodedRegion = floodFill(floodedGarden, new Vec2({ x, y })) price += floodedRegion.perimeter * floodedRegion.points.length } @@ -185,7 +172,7 @@ const part2 = (data: Garden): number => { for (let y = 0; y < floodedGarden.length; y++) { for (let x = 0; x < floodedGarden.length; x++) { if (floodedGarden[y][x] !== '.') { - const floodedRegion = floodFill(floodedGarden, { x, y }) + const floodedRegion = floodFill(floodedGarden, new Vec2({ x, y })) price += floodedRegion.sides * floodedRegion.points.length } diff --git a/2024/d13/index.ts b/2024/d13/index.ts index eb1d857..512a3a0 100644 --- a/2024/d13/index.ts +++ b/2024/d13/index.ts @@ -2,7 +2,7 @@ import { readFileSync } from 'node:fs' import { Context, init as initZ3, IntNum } from 'z3-solver' import { runExamples, runSolution } from '@magiczne/advent-of-code-ts-core/aoc' -import type { Vec2 } from '@magiczne/advent-of-code-ts-core/types' +import { Vec2 } from '@magiczne/advent-of-code-ts-core/math' interface Machine { buttonA: Vec2 @@ -11,9 +11,11 @@ interface Machine { } const { Context } = await initZ3() + +// @ts-expect-error Something is wrong with z3-solver const ctx: Context = new Context('aoc') -const optimizeMachine = async (machine: Machine, prizeCoefficient): Promise => { +const optimizeMachine = async (machine: Machine, prizeCoefficient = 0): Promise => { const solver = new ctx.Optimize() const x = ctx.Int.const('x') const y = ctx.Int.const('y') @@ -73,18 +75,18 @@ const reader = (file: string): ReadonlyArray => { const lines = machine.split('\n').map(line => line.match(/(\d+).+?(\d+)/)) return { - buttonA: { + buttonA: new Vec2({ x: parseInt(lines[0][1], 10), y: parseInt(lines[0][2], 10), - }, - buttonB: { + }), + buttonB: new Vec2({ x: parseInt(lines[1][1], 10), y: parseInt(lines[1][2], 10), - }, - prize: { + }), + prize: new Vec2({ x: parseInt(lines[2][1], 10), y: parseInt(lines[2][2], 10), - }, + }), } }) } diff --git a/2024/d14/index.ts b/2024/d14/index.ts index bc2321e..c647118 100644 --- a/2024/d14/index.ts +++ b/2024/d14/index.ts @@ -3,7 +3,7 @@ import { sep } from 'node:path' import { createInterface } from 'node:readline/promises' import { runExamples, runSolution } from '@magiczne/advent-of-code-ts-core/aoc' -import { Vec2 } from '@magiczne/advent-of-code-ts-core/types' +import { Vec2 } from '@magiczne/advent-of-code-ts-core/math' import { group } from 'radash' interface Robot { @@ -67,10 +67,10 @@ const part1 = (data: Input): number => { const positiveSpeedY = robot.speed.y > 0 ? robot.speed.y : data.mapSize.y - Math.abs(robot.speed.y) return { - position: { + position: new Vec2({ x: (robot.position.x + positiveSpeedX * SECONDS) % data.mapSize.x, y: (robot.position.y + positiveSpeedY * SECONDS) % data.mapSize.y, - }, + }), speed: robot.speed, } }) @@ -95,10 +95,10 @@ const part2 = async (data: Input): Promise => { const positiveSpeedY = robot.speed.y > 0 ? robot.speed.y : data.mapSize.y - Math.abs(robot.speed.y) return { - position: { + position: new Vec2({ x: (robot.position.x + positiveSpeedX) % data.mapSize.x, y: (robot.position.y + positiveSpeedY) % data.mapSize.y, - }, + }), speed: robot.speed, } }) @@ -118,8 +118,8 @@ const reader = (file: string): Input => { return { mapSize: { - '0.txt': { x: 11, y: 7 }, - 'input.txt': { x: 101, y: 103 }, + '0.txt': new Vec2({ x: 11, y: 7 }), + 'input.txt': new Vec2({ x: 101, y: 103 }), }[fileName], robots: readFileSync(file, 'utf-8') .trim() @@ -128,14 +128,14 @@ const reader = (file: string): Input => { const match = line.match(/(\d+),(\d+) v=([-\d]+),([-\d]+)/) return { - position: { + position: new Vec2({ x: parseInt(match[1], 10), y: parseInt(match[2], 10), - }, - speed: { + }), + speed: new Vec2({ x: parseInt(match[3], 10), y: parseInt(match[4], 10), - }, + }), } }), } diff --git a/ts-core/math/direction.ts b/ts-core/math/direction.ts index 3b34053..310326a 100644 --- a/ts-core/math/direction.ts +++ b/ts-core/math/direction.ts @@ -16,6 +16,10 @@ class Direction { static get left(): Vec2 { return new Vec2({ x: -1, y: 0 }) } + + static get cardnial(): [Vec2, Vec2, Vec2, Vec2] { + return [Direction.up, Direction.right, Direction.down, Direction.left] + } } export { Direction } diff --git a/ts-core/math/vec2.ts b/ts-core/math/vec2.ts index 6c92a41..0f96802 100644 --- a/ts-core/math/vec2.ts +++ b/ts-core/math/vec2.ts @@ -1,28 +1,32 @@ -import type { Vec2 as IVec2 } from '../types' +import type { IVec2 } from '../types' class Vec2 implements IVec2 { public x: number public y: number - constructor({ x, y }: IVec2 = { x: 0, y: 0 }) { + constructor({ x, y } = { x: 0, y: 0 }) { this.x = x this.y = y } - add(vec2: IVec2): Vec2 { + add(other: IVec2): Vec2 { return new Vec2({ - x: this.x + vec2.x, - y: this.y + vec2.y, + x: this.x + other.x, + y: this.y + other.y, }) } - sub(vec2: IVec2): Vec2 { + sub(other: IVec2): Vec2 { return new Vec2({ - x: this.x - vec2.x, - y: this.y - vec2.y, + x: this.x - other.x, + y: this.y - other.y, }) } + equals(other: IVec2): boolean { + return this.x === other.x && this.y === other.y + } + clone(): Vec2 { return new Vec2({ x: this.x, @@ -30,16 +34,14 @@ class Vec2 implements IVec2 { }) } - updateInPlace(vec2: IVec2): void { - this.x = vec2.x - this.y = vec2.y + addInPlace(other: IVec2): void { + this.x += other.x + this.y += other.y } - static fromInterface(vec2: IVec2): Vec2 { - return new Vec2({ - x: vec2.x, - y: vec2.y, - }) + updateInPlace(other: IVec2): void { + this.x = other.x + this.y = other.y } } diff --git a/ts-core/types/Vec2.ts b/ts-core/types/Vec2.ts index 83bea16..f172346 100644 --- a/ts-core/types/Vec2.ts +++ b/ts-core/types/Vec2.ts @@ -1,6 +1,6 @@ -interface Vec2 { +interface IVec2 { x: number y: number } -export type { Vec2 } +export type { IVec2 }