This commit is contained in:
nim-ka
2022-11-25 04:23:55 +00:00
parent efddeee1d3
commit d5fcd1c488
3 changed files with 179 additions and 2 deletions

177
2021/23.js Normal file
View File

@@ -0,0 +1,177 @@
const statesArr = []
const stateIdxs = {}
function encodeState(arr) {
let key = arr.join("")
if (!(key in stateIdxs)) {
stateIdxs[key] = statesArr.push(arr) - 1
}
return stateIdxs[key]
}
function decodeState(num) {
return statesArr[num]
}
// 0 is hallway, 1 is A room, 2 is B room, etc
function getRoom(pos) {
if (pos < 11) {
return 0
}
return ((pos - 11) % 4) + 1
}
let hallwayStops = [0, 1, 3, 5, 7, 9, 10]
let roomPoses = []
function possibleStates(num) {
let state = decodeState(num)
let newStates = []
for (let pos = 0; pos < state.length; pos++) {
let amphipod = state[pos]
if (!amphipod) {
continue
}
let curRoom = getRoom(pos)
let roomEntrance = 2 * curRoom
let destRoomEntrance = 2 * amphipod
let curRoomPoses = roomPoses[getRoom(pos)]
let destRoomPoses = roomPoses[amphipod]
let depthInRoom = curRoomPoses?.indexOf(pos)
if (curRoom == amphipod && curRoomPoses.slice(depthInRoom).every((e) => state[e] == amphipod)) {
continue
}
let dests = []
let destRoomAvailable = destRoomPoses.every((pos) => state[pos] == 0 || state[pos] == amphipod)
let steps = 0
let hallwayPos
if (curRoom != 0) {
if (curRoomPoses.slice(0, depthInRoom).some((pos) => state[pos] != 0)) {
continue
}
destRoomAvailable &&= roomEntrance != destRoomEntrance
steps = depthInRoom + 1
hallwayPos = roomEntrance
} else {
hallwayPos = pos
}
let destRoomSteps = -1
let leftPath = hallwayStops.filter((pos) => pos < hallwayPos).reverse()
let rightPath = hallwayStops.filter((pos) => pos > hallwayPos)
let leftBlock = leftPath.findIndex((pos) => state[pos] != 0)
let rightBlock = rightPath.findIndex((pos) => state[pos] != 0)
let leftDests = (leftBlock > -1 ? leftPath.slice(0, leftBlock) : leftPath)
.map((pos) => [pos, steps + hallwayPos - pos])
let rightDests = (rightBlock > -1 ? rightPath.slice(0, rightBlock) : rightPath)
.map((pos) => [pos, steps + pos - hallwayPos])
if (curRoom != 0) {
dests.push(...leftDests, ...rightDests)
}
if (destRoomAvailable) {
destRoomSteps =
[...leftDests, [hallwayPos, steps]].find((e) => e[0] == destRoomEntrance + 1)?.[1] ??
[...rightDests, [hallwayPos, steps]].find((e) => e[0] == destRoomEntrance - 1)?.[1] ?? -1
}
if (destRoomSteps > -1) {
let destRoomBlock = destRoomPoses.findIndex((pos) => state[pos] != 0)
let destPosIdx = (destRoomBlock > -1 ? destRoomBlock : destRoomPoses.length) - 1
dests.push([destRoomPoses[destPosIdx], destRoomSteps + 2 + destPosIdx])
}
newStates.push(...dests.map((e) => {
let newState = state.copy()
newState[pos] = 0
newState[e[0]] = amphipod
return { state: encodeState(newState), energy: e[1] * [1, 10, 100, 1000][amphipod - 1] }
}))
}
return newStates
}
function isSolved(num) {
let state = decodeState(num)
return roomPoses.every((poses, i) => poses.every((pos) => state[pos] == i))
}
function day23(input, part2) {
let lines = input.split("\n")
if (part2) {
lines.splice(3, 0, " #D#C#B#A#", " #D#B#A#C#")
}
for (let i = 1; i <= 4; i++) {
roomPoses[i] = Array(part2 ? 4 : 2).fill().map((_, j) => 10 + j * 4 + i)
}
let state = encodeState(lines.join("").replace(/[# ]/g, "")
.replaceAll(".", 0)
.replaceAll("A", 1)
.replaceAll("B", 2)
.replaceAll("C", 3)
.replaceAll("D", 4).split("").num())
let energies = {}
energies[state] = 0
let stateHeap = new BinHeap((state1, state2) => state1.totalEnergy < state2.totalEnergy)
stateHeap.insert({ state: state, totalEnergy: 0 })
for (let i = 0; ; i++) {
let top = stateHeap.extract()
if (isSolved(top.state)) {
return top.totalEnergy
}
for (let res of possibleStates(top.state)) {
let energy = top.totalEnergy + res.energy
if (res.state in energies) {
let idx = stateHeap.data.findIndex((e) => e.state == res.state)
if (idx > -1 && energy < stateHeap.data[idx].totalEnergy) {
stateHeap.data[idx].totalEnergy = energy
stateHeap.up(idx)
}
} else {
energies[res.state] = energy
stateHeap.insert({ state: res.state, totalEnergy: energy })
}
}
if (i % 10000 == 0) {
console.log("iteration", i, "heap size", stateHeap.data.length, "min energy", top.totalEnergy)
}
}
}
if (typeof window == "undefined") {
module.exports = day23
}

2
out.js
View File

@@ -1244,7 +1244,7 @@ if (typeof window == "undefined" && process.argv[2] == "test") {
const year = "2021"
for (let i = +process.argv[3] || 1; i <= 22; i++) {
for (let i = +process.argv[3] || 1; i <= 23; i++) {
const func = require(`./${year}/${i}.js`)
const input = fs.readFileSync(`./${year}/inputs/${i}`, "utf8")
const answers = fs.readFileSync(`./${year}/answers/${i}`, "utf8").split("\n-----\n")

View File

@@ -3,7 +3,7 @@ if (typeof window == "undefined" && process.argv[2] == "test") {
const year = "2021"
for (let i = +process.argv[3] || 1; i <= 22; i++) {
for (let i = +process.argv[3] || 1; i <= 23; i++) {
const func = require(`./${year}/${i}.js`)
const input = fs.readFileSync(`./${year}/inputs/${i}`, "utf8")
const answers = fs.readFileSync(`./${year}/answers/${i}`, "utf8").split("\n-----\n")