Skip to content

Commit

Permalink
2024 Day 08
Browse files Browse the repository at this point in the history
  • Loading branch information
Magiczne committed Dec 8, 2024
1 parent 30b8372 commit bb9e613
Show file tree
Hide file tree
Showing 9 changed files with 289 additions and 6 deletions.
12 changes: 6 additions & 6 deletions 2024/d06/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,24 @@ const rotate = (speed: Vec2): Vec2 => {
x: -1,
y: 0,
}
}
}

// From going left to going upwards
if (speed.x === -1 && speed.y === 0) {
return {
x: 0,
y: -1,
}
}
}

// From going upwards to going right
if (speed.x === 0 && speed.y === -1) {
return {
x: 1,
y: 0,
}
}
}

// From going right to going downwards
if (speed.x === 1 && speed.y === 0) {
return {
Expand Down
180 changes: 180 additions & 0 deletions 2024/d08/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
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'

type Antenna = Vec2 & { type: 'Antenna'; code: string }
type Antinode = { type: 'Antinode'; code: string }
type MapItem = null | Antenna | Antinode
type Map = Array<Array<MapItem>>

interface Input {
map: Map
antennas: Record<string, Array<Antenna>>
}

const DEBUG = false
const printMap = (map: Map): void => {
if (!DEBUG) {
return
}

map.forEach(row => {
let rowString = ''

row.forEach(cell => {
if (cell.type === 'Antenna') {
rowString += cell.code
} else if (cell.type === 'Antinode') {
rowString += '#'
} else {
rowString += '.'
}
})

console.log(rowString)
})

console.log('')
}

const part1 = (input: Input): number => {
const map = structuredClone(input.map)

Object.values(input.antennas).forEach(antennaSet => {
combinationsWithoutRepetition(antennaSet, 2).forEach(([firstNode, secondNode]) => {
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 antinodes: ReadonlyArray<Vec2> = [
{
x: firstNode.x - firstAntinodeDir.x * distanceX,
y: firstNode.y - firstAntinodeDir.y * distanceY,
},
{
x: secondNode.x - secondAntinodeDir.x * distanceX,
y: secondNode.y - secondAntinodeDir.y * distanceY,
},
]

antinodes.forEach(antinode => {
if (map[antinode.y]?.[antinode.x] !== undefined) {
map[antinode.y][antinode.x] = { type: 'Antinode', code: firstNode.code }
}
})
})
})

printMap(map)

return map
.map(row => {
return row.reduce((acc, item) => {
if (item?.type === 'Antinode') {
return acc + 1
}

return acc
}, 0)
})
.reduce((acc, rowCount) => acc + rowCount, 0)
}

const part2 = (input: Input): number => {
const map = structuredClone(input.map)

Object.values(input.antennas).forEach(antennaSet => {
combinationsWithoutRepetition(antennaSet, 2).forEach(([firstNode, secondNode]) => {
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 }

let antinodes: Array<Vec2> = []

// Generate antinodes in first direction
for (let i = 1; ; i++) {
const x = firstNode.x - firstAntinodeDir.x * (distanceX * i)
const y = firstNode.y - firstAntinodeDir.y * (distanceY * i)

if (map[y]?.[x] === undefined) {
break
}

antinodes.push({ x, y })
}

// Generate antinodes in second direction
for (let i = 1; ; i++) {
const x = secondNode.x - secondAntinodeDir.x * (distanceX * i)
const y = secondNode.y - secondAntinodeDir.y * (distanceY * i)

if (map[y]?.[x] === undefined) {
break
}

antinodes.push({ x, y })
}

antinodes.forEach(antinode => {
if (map[antinode.y]?.[antinode.x] !== undefined) {
map[antinode.y][antinode.x] = { type: 'Antinode', code: firstNode.code }
}
})
})
})

printMap(map)

return map
.map(row => {
return row.reduce((acc, item) => {
if (item !== null) {
return acc + 1
}

return acc
}, 0)
})
.reduce((acc, rowCount) => acc + rowCount, 0)
}

const reader = (file: string): Input => {
const map = readFileSync(file, 'utf-8')
.trim()
.split('\n')
.map((line, y) => {
return line.split('').map((item, x) => {
if (item === '.') {
return null
}

return {
type: 'Antenna',
code: item,
x,
y,
}
})
})

const antennas = Object.groupBy(
map.flatMap(row => {
return row.filter(item => item !== null)
}),
antenna => antenna.code,
)

return {
antennas: antennas as Record<string, Array<Antenna>>,
map: map as Array<Array<MapItem>>,
}
}

runExamples(2024, '08', reader, part1, part2)
runSolution(2024, '08', reader, part1, part2)
50 changes: 50 additions & 0 deletions 2024/d08/input.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
..........................4..............7..q.....
..........G..42.f......K.........7................
D.t...S......A....................................
..K.................................I.............
G....D...f.tA..H.S..........o................N....
t....f..............4..A........B.........N.....q.
...b...k....f..h..........6.......................
..........b....m................7...............Q.
....h....G.2........K.i...........................
.F...2.....D....H..6..o........I..................
k.......b..................K......I.....e.....B...
.............Sp..o....n....R.............N........
F............d................2...................
.........i........................................
.....ma.....d......p.Q..n.....7....9..........N...
......m..H......S...8......n.....Q...e............
.i..............8......O.....I................c...
..d......k....R.....................9....z........
..p.......m......n...............P................
.......pLb...................W..j................q
.....C..1..........u.....c.....jO...Z..o.........V
..C.....i........X1......9......e....j.....B....c.
......................9...........Q..Z............
.d....h..L...............8........O...............
....C....r..L....R...............6................
...........h.............1.t......P.......V.......
.......L.1........................................
..................................................
X.......................................V.....W...
rx........a.X.......0....l..........6.........z...
..r........a.8.................................z..
................w.........l..............P....A...
..........E....s..w.j........l...............W....
...v...............c..............W..y...V.O......
.....X..g.Y...0w......l...................u.......
.C.......Y...0....................................
...g..UJ...0........v.............................
.U...aY...........................................
....5........Y....MUJ..........B..................
.......g...5M........J.......w.........u..Z.......
................TE................................
..U....r....5.................J..........Z........
.......5...3......s........T......................
.............E.T..............................u...
...........v........y.......................P.....
................s.................................
x............M3........e..........................
........3...v......MT.............................
.............x....................................
....x..........3............y.....................
12 changes: 12 additions & 0 deletions 2024/d08/test-runs/0.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
............
........0...
.....0......
.......0....
....0.......
......A.....
............
............
........A...
.........A..
............
............
10 changes: 10 additions & 0 deletions 2024/d08/test-runs/1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
T.........
...T......
.T........
..........
..........
..........
..........
..........
..........
..........
23 changes: 23 additions & 0 deletions ts-core/combinatorics/combinations-without-repetition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const combinationsWithoutRepetition = <T>(items: ReadonlyArray<T>, length: number): ReadonlyArray<ReadonlyArray<T>> => {
const result: Array<ReadonlyArray<T>> = []

const backtrack = (combination: Array<T>, start: number): void => {
if (combination.length === length) {
result.push([...combination])

return
}

for (let i = start; i < items.length; i++) {
combination.push(items[i])
backtrack(combination, i + 1)
combination.pop()
}
}

backtrack([], 0)

return result
}

export { combinationsWithoutRepetition }
1 change: 1 addition & 0 deletions ts-core/combinatorics/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { combinations } from './combinations'
export { combinationsWithoutRepetition } from './combinations-without-repetition'
6 changes: 6 additions & 0 deletions ts-core/types/Vec2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
interface Vec2 {
x: number
y: number
}

export type { Vec2 }
1 change: 1 addition & 0 deletions ts-core/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type * from './Vec2'

0 comments on commit bb9e613

Please sign in to comment.