199 lines
5.0 KiB
TypeScript
199 lines
5.0 KiB
TypeScript
import { open } from 'node:fs/promises';
|
|
|
|
const file = await open('./inputs/14.example');
|
|
|
|
let input = (await file.readFile()).toString().split('\n').map(e => e.split(""))
|
|
|
|
class Rock {
|
|
x: number
|
|
y: number
|
|
amount: number
|
|
neighbours: {
|
|
left: Rock[]
|
|
right: Rock[]
|
|
top: Rock[]
|
|
bottom: Rock[]
|
|
}
|
|
|
|
constructor(y: number, x: number) {
|
|
this.x = x
|
|
this.y = y
|
|
this.amount = 0
|
|
this.neighbours = {
|
|
left: [],
|
|
right: [],
|
|
top: [],
|
|
bottom: []
|
|
}
|
|
}
|
|
}
|
|
|
|
function fallToUp({ x, y }: { x: number, y: number }) {
|
|
let index = input.slice(0, y).findLastIndex(e => e[x] === '#' || e[x] === 'O')
|
|
input[y][x] = '.'
|
|
input[index + 1][x] = 'O'
|
|
}
|
|
// Make all boulders align to the bottom of rocks
|
|
input.forEach((row, rowIndex) => {
|
|
row.forEach((el, colIndex) => {
|
|
if (el === 'O') {
|
|
fallToUp({ x: colIndex, y: rowIndex })
|
|
}
|
|
})
|
|
})
|
|
|
|
// Add outer rocks
|
|
input.unshift("#".repeat(input[0].length).split(''))
|
|
input.push("#".repeat(input[0].length).split(''))
|
|
input.forEach(e => {
|
|
e.push('#')
|
|
e.unshift('#')
|
|
})
|
|
|
|
const rocks: Rock[] = []
|
|
input.forEach((row, rowIndex) => {
|
|
row.forEach((el, columnIndex) => {
|
|
if (el === "#") {
|
|
rocks.push(new Rock(rowIndex, columnIndex))
|
|
}
|
|
})
|
|
})
|
|
// Populate rocks and neighbours
|
|
rocks.forEach(e => {
|
|
const firstAtLeft = rocks.findLast(f => f.x < e.x && f.y === e.y)?.x ?? 0
|
|
|
|
const firstAtRight = rocks.find(f => f.x > e.x && f.y === e.y)?.x ?? input[0].length - 1
|
|
// e.neighbours.right = rocks.filter(f => e.y > f.y && e.x < f.x && firstAtRight > f.x)
|
|
|
|
const firstAtTop = rocks.findLast(f => f.y < e.y && f.x === e.x)?.y ?? 0
|
|
// e.neighbours.top = rocks.filter(f => e.y > f.y && e.x > f.x && firstAtTop < f.y)
|
|
|
|
const firstAtBottom = rocks.find(f => f.y > e.y && f.x === e.x)?.y ?? input.length - 1
|
|
// e.neighbours.bottom = rocks.filter(f => e.y < f.y && e.x > f.x && firstAtbottom > f.y)
|
|
|
|
//Roll Right
|
|
for (let i = firstAtBottom - 1; i > e.y; i--) {
|
|
e.neighbours.right.push(
|
|
rocks.filter(f => f.y === i && f.x > e.x)
|
|
.reduce((prev, curr) => {
|
|
if (curr.x < prev.x) return curr
|
|
return prev
|
|
})
|
|
)
|
|
}
|
|
e.neighbours.right.reverse()
|
|
|
|
//Roll Top
|
|
for (let i = firstAtRight - 1; i > e.x; i--) {
|
|
e.neighbours.top.push(
|
|
rocks.filter(f => f.x === i && f.y < e.y)
|
|
.reduce((prev, curr) => {
|
|
if (curr.y > prev.y) return curr
|
|
return prev
|
|
})
|
|
)
|
|
}
|
|
|
|
e.neighbours.top.reverse()
|
|
|
|
//Roll Left
|
|
for (let i = firstAtTop + 1; i < e.y; i++) {
|
|
e.neighbours.left.push(
|
|
rocks.filter(f => f.y === i && f.x < e.x)
|
|
.reduce((prev, curr) => {
|
|
if (curr.x > prev.x) return curr
|
|
return prev
|
|
})
|
|
)
|
|
}
|
|
e.neighbours.left.reverse()
|
|
//Roll Bottom
|
|
for (let i = firstAtLeft + 1; i < e.x; i++) {
|
|
e.neighbours.bottom.push(
|
|
rocks.filter(f => f.x === i && f.y > e.y)
|
|
.reduce((prev, curr) => {
|
|
if (curr.y < prev.y) return curr
|
|
return prev
|
|
})
|
|
)
|
|
}
|
|
e.neighbours.bottom.reverse()
|
|
})
|
|
|
|
const rightOrder = [...rocks]
|
|
rightOrder.sort((a, b) => {
|
|
if (a.x < b.x) return 1
|
|
if (a.x > b.x) return -1
|
|
return 0
|
|
})
|
|
|
|
const leftOrder = [...rocks]
|
|
leftOrder.sort((a, b) => {
|
|
if (a.x > b.x) return 1
|
|
if (a.x < b.x) return -1
|
|
return 0
|
|
})
|
|
|
|
const topOrder = [...rocks]
|
|
topOrder.sort((a, b) => {
|
|
if (a.y > b.y) return 1
|
|
if (a.y < b.y) return -1
|
|
return 0
|
|
})
|
|
|
|
const bottomOrder = [...rocks]
|
|
bottomOrder.sort((a, b) => {
|
|
if (a.y < b.y) return 1
|
|
if (a.y > b.y) return -1
|
|
return 0
|
|
})
|
|
|
|
// Populate bounders for each rock
|
|
rocks.forEach(r => {
|
|
let offset = 1
|
|
while (r.y + offset < input.length && input[r.y + offset][r.x] !== '#' && input[r.y + offset][r.x] !== '.') {
|
|
r.amount++
|
|
offset++
|
|
}
|
|
})
|
|
|
|
rightOrder.forEach(r => {
|
|
r.neighbours.right.splice(0, r.amount).forEach(n => n.amount++)
|
|
r.amount = 0
|
|
})
|
|
|
|
bottomOrder.forEach(r => {
|
|
r.neighbours.bottom.splice(0, r.amount).forEach(n => n.amount++)
|
|
r.amount = 0
|
|
})
|
|
|
|
leftOrder.forEach(r => {
|
|
r.neighbours.left.splice(0, r.amount).forEach(n => n.amount++)
|
|
r.amount = 0
|
|
})
|
|
|
|
for (let i = 0; i < 999999999; i++) {
|
|
topOrder.forEach(r => {
|
|
r.neighbours.top.splice(0, r.amount).forEach(n => n.amount++)
|
|
r.amount = 0
|
|
})
|
|
|
|
rightOrder.forEach(r => {
|
|
r.neighbours.right.splice(0, r.amount).forEach(n => n.amount++)
|
|
r.amount = 0
|
|
})
|
|
|
|
bottomOrder.forEach(r => {
|
|
r.neighbours.bottom.splice(0, r.amount).forEach(n => n.amount++)
|
|
r.amount = 0
|
|
})
|
|
|
|
leftOrder.forEach(r => {
|
|
r.neighbours.left.splice(0, r.amount).forEach(n => n.amount++)
|
|
r.amount = 0
|
|
})
|
|
}
|
|
|
|
const sum = 0
|
|
|
|
console |