This commit is contained in:
Joshua Seigler 2024-12-15 03:01:44 -05:00
parent 4803b87dad
commit 57455999f4
4 changed files with 246 additions and 13 deletions

View file

@ -223,16 +223,16 @@
},
{
"part1": {
"solved": false,
"result": null,
"solved": true,
"result": "1446158",
"attempts": [],
"time": null
"time": 4.47472
},
"part2": {
"solved": false,
"result": null,
"solved": true,
"result": "1446175",
"attempts": [],
"time": null
"time": 7.353299
}
},
{

View file

@ -25,7 +25,7 @@
[![Day](https://badgen.net/badge/12/%E2%98%85%E2%98%85/green)](src/day12)
[![Day](https://badgen.net/badge/13/%E2%98%85%E2%98%85/green)](src/day13)
[![Day](https://badgen.net/badge/14/%E2%98%85%E2%98%86/yellow)](src/day14)
![Day](https://badgen.net/badge/15/%E2%98%86%E2%98%86/gray)
[![Day](https://badgen.net/badge/15/%E2%98%85%E2%98%85/green)](src/day15)
![Day](https://badgen.net/badge/16/%E2%98%86%E2%98%86/gray)
![Day](https://badgen.net/badge/17/%E2%98%86%E2%98%86/gray)
![Day](https://badgen.net/badge/18/%E2%98%86%E2%98%86/gray)
@ -160,16 +160,16 @@ Both parts: 1.913ms
```
Day 14
Time part 1: 1.507ms
Time part 1: 1.492ms
Time part 2: -
Both parts: 1.507ms
Both parts: 1.492ms
```
```
Day 15
Time part 1: -
Time part 2: -
Both parts: -
Time part 2: 7.672ms
Both parts: 7.672ms
```
```
@ -243,8 +243,8 @@ Both parts: -
```
```
Total stars: 27/50
Total time: 38905.685ms
Total stars: 29/50
Total time: 38913.342ms
```
<!--/RESULTS-->

9
src/day15/README.md Normal file
View file

@ -0,0 +1,9 @@
# 🎄 Advent of Code 2024 - day 15 🎄
## Info
Task description: [link](https://adventofcode.com/2024/day/15)
## Notes
...

224
src/day15/index.ts Normal file
View file

@ -0,0 +1,224 @@
import run from "aocrunner"
type Coord = [number, number]
const getKey = (r: number, c: number) => {
return r * 100 + c
}
type Key = ReturnType<typeof getKey>
const deltas: Record<string, Coord> = {
"^": [-1, 0],
">": [0, 1],
v: [1, 0],
"<": [0, -1],
}
const part1 = (rawInput: string) => {
// Parsing
const [rawMap, rawMovements] = rawInput.split("\n\n")
const map = rawMap.split("\n").map(line => line.split(''))
let start: Coord
let boxes = new Set<Key>()
const walls = new Set<Key>()
map.forEach((line, r) => {
line.forEach((cell, c) => {
const key = getKey(r, c)
if (cell === "O") {
boxes.add(key)
}
if (cell === "@") {
start = [r, c]
}
if (cell === "#") {
walls.add(key)
}
})
})
const movements = rawMovements.replaceAll("\n", "").split("")
// Solving
let [rPos, cPos] = start
movements.forEach((move) => {
const [dr, dc] = deltas[move]
for (let i = 1; ; i++) {
const key = getKey(rPos + dr * i, cPos + dc * i)
if (walls.has(key)) return // no space before hitting wall, do nothing
if (boxes.has(key)) continue // only boxes so far
// an open space!
if (i > 1) {
boxes.delete(getKey(rPos+dr, cPos+dc))
boxes.add(key)
break
}
break
}
rPos += dr
cPos += dc
// Uncomment to show moves
// console.log(move)
// map.forEach((row,r) => {
// const line = row.map((_, c) => {
// const key = getKey(r,c)
// if (boxes.has(key)) return "O"
// if (walls.has(key)) return "#"
// if (rPos === r && cPos === c) return "@"
// return " "
// }).join('')
// console.log(line)
// })
// console.log('')
})
return Array.from(boxes.values()).reduce((total, b) => total + b, 0)
}
const part2 = (rawInput: string) => {
// Parsing
const [rawMap, rawMovements] = rawInput.split("\n\n")
const map = rawMap.split("\n").map(line => line.split(''))
let start: Coord
let boxes = new Set<Key>()
const walls = new Set<Key>()
map.forEach((line, r) => {
line.forEach((cell, c) => {
const key = getKey(r, c * 2)
if (cell === "O") {
boxes.add(key)
}
if (cell === "@") {
start = [r, c * 2]
}
if (cell === "#") {
walls.add(key)
walls.add(getKey(r, 2 * c + 1))
}
})
})
const movements = rawMovements.replaceAll("\n", "").split("")
// Solving
let [rPos, cPos] = start
movements.forEach((instruction) => {
const [dr, dc] = deltas[instruction]
if (dr === 0) { // horizontal movement
for (let i = 1; ; i++) {
const key = getKey(rPos, cPos + dc * i)
if (walls.has(key)) return // no space before hitting wall, do nothing
if (dc > 0 && boxes.has(key)) {
i++
continue
}
if (dc < 0 && boxes.has(getKey(rPos, cPos - i - 1))) {
i++
continue
}
// an open space!
if (i > 1) {
for (let j = 1; j < i; j += 2) {
const offset = dc < 0 ? 1 : 0
boxes.delete(getKey(rPos, cPos+(j+offset)*dc))
boxes.add(getKey(rPos, cPos+(j+offset+1)*dc))
}
break
}
break
}
}
// vertical movement, dc is 0
const toDelete: Key[] = []
const toAdd: Key[] = []
// solve this with recursion!
const move = (r: number, c: number, dr: number): boolean => {
const keyAhead = getKey(r + dr, c)
if (walls.has(keyAhead)) return false
if (boxes.has(keyAhead)) {
if (move(r + dr, c, dr) && move(r + dr, c + 1, dr)) {
toDelete.push(keyAhead)
toAdd.push(getKey(r+2*dr, c))
return true
}
return false
}
const keyLeftAhead = getKey(r + dr, c-1)
if (boxes.has(keyLeftAhead)) {
if (move(r + dr, c - 1, dr) && move(r + dr, c, dr)) {
toDelete.push(keyLeftAhead)
toAdd.push(getKey(r + 2*dr, c - 1))
return true
}
return false
}
return true
}
if (move(rPos, cPos, dr)) {
toDelete.forEach(k => boxes.delete(k))
toAdd.forEach(k => boxes.add(k))
} else {
return
}
rPos += dr
cPos += dc
// Uncomment to show moves
// console.log(instruction)
// map.forEach((row,r) => {
// const line = new Array(row.length * 2).fill(0).map((_, c) => {
// const key = getKey(r,c)
// if (rPos === r && cPos === c) return "@"
// if (boxes.has(key)) return "["
// if (boxes.has(getKey(r, c-1))) return "]"
// if (walls.has(key)) return "#"
// return "."
// }).join('')
// console.log(line)
// })
// console.log('')
})
return Array.from(boxes.values()).reduce((total, b) => total + b, 0)
}
run({
part1: {
tests: [
{
input: `########
#..O.O.#
##@.O..#
#...O..#
#.#.O..#
#...O..#
#......#
########
<^^>>>vv<v>>v<<`,
expected: 2028,
},
],
solution: part1,
},
part2: {
tests: [
{
input: `#######
#...#.#
#.....#
#..OO@#
#..O..#
#.....#
#######
<vv<<^^<<^^`,
expected: 618,
},
],
solution: part2,
},
trimTestInputs: true,
onlyTests: false,
})