55 lines
1.5 KiB
JavaScript
55 lines
1.5 KiB
JavaScript
function encodePoint(pt) {
|
|
return (pt.x << 9) | pt.y
|
|
}
|
|
|
|
function decodePoint(num) {
|
|
return new Point((num >> 9) & 0b111111111, num & 0b111111111)
|
|
}
|
|
|
|
function day15(input, part2) {
|
|
let grid = Grid.fromStr(input).num()
|
|
|
|
if (part2) {
|
|
grid = new Grid(grid.width * 5, grid.height * 5)
|
|
.mapMut((e, pt) => grid.get(new Pt(pt.x % grid.width, pt.y % grid.height)) + (pt.x / grid.width | 0) + (pt.y / grid.height | 0))
|
|
.mapMut((e) => ((e - 1) % 9) + 1)
|
|
}
|
|
|
|
let start = encodePoint(new Point(0, 0))
|
|
|
|
let visited = {}
|
|
visited[start] = true
|
|
|
|
let heap = new BinHeap((a, b) => a.risk < b.risk)
|
|
heap.insert({ pt: start, risk: 0 })
|
|
|
|
while (true) {
|
|
let top = heap.extract()
|
|
let decoded = decodePoint(top.pt)
|
|
|
|
if (decoded.x == grid.width - 1 && decoded.y == grid.height - 1) {
|
|
return top.risk
|
|
}
|
|
|
|
for (let pt of grid.getAdjNeighbors(decoded)) {
|
|
let encoded = encodePoint(pt)
|
|
let risk = top.risk + grid.get(pt)
|
|
|
|
if (encoded in visited) {
|
|
let idx = heap.data.findIndex((e) => e.pt == encoded)
|
|
if (idx > -1 && risk < heap.data[idx].risk) {
|
|
heap.data[idx].risk = risk
|
|
heap.up(idx)
|
|
}
|
|
} else {
|
|
visited[encoded] = true
|
|
heap.insert({ pt: encoded, risk: risk })
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (typeof window == "undefined") {
|
|
module.exports = day15
|
|
}
|