Last active
January 23, 2023 09:51
-
-
Save p-a/b818938caddea82cea5346c42d94e3c2 to your computer and use it in GitHub Desktop.
AoC 2022 Day 22 Revisited
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { map, sum } from "../../lib/arrays.js"; | |
import { gcd } from "../../lib/math.js"; | |
import { pipe } from "../../lib/utils.js"; | |
const parse = input => { | |
const grp = input.split("\n\n"); | |
const net = grp[0] | |
.split("\n") | |
.map(([...line]) => line.map(c => c.trim())); | |
const instr = [...`R${grp[1]}`.matchAll(/(([LR])(\d*))/g)] | |
.map(([, , a, b]) => [a, b]) | |
.map(([a, b]) => [a === "L" ? -1 : 1, Number(b) || 0]); | |
const dim = [ | |
Math.max(...net.map(r => r.length)), | |
net.length, | |
]; | |
return [ | |
net, | |
instr, | |
[[net[0].indexOf("."), 0], 3], | |
dim, | |
gcd(...dim), | |
]; | |
}; | |
// prettier-ignore | |
const DIR = [[1, 0],[0, 1],[-1, 0],[0, -1]]; | |
const walkFlatEarth = ([net, instr, start, dim]) => | |
instr.reduce(([p, f], [turn, steps]) => { | |
f = (f + 4 + turn) % 4; | |
let pos, c; | |
while ((c = net[p[1]][p[0]]) !== "#" && steps >= 0) { | |
if (c) { | |
pos = p; | |
steps--; | |
} | |
p = DIR[f].map( | |
(d, i) => (p[i] + d + dim[i]) % dim[i] | |
); | |
} | |
return [pos, f]; | |
}, start); | |
/* e------f | |
/| /| | |
a------b | | |
| g----|-h | |
|/ |/ Roll around a cube *underneath* a cube net and | |
c------d store fronting face's top-left coordinates and edges. | |
*/ | |
// prettier-ignore | |
const DIR_ROT = w => [ | |
[ 0, w, ([a, b, c, d, e, f, g, h]) => [c, d, g, h, a, b, e, f]], | |
[ 0,-w, ([a, b, c, d, e, f, g, h]) => [e, f, a, b, g, h, c, d]], | |
[ w, 0, ([a, b, c, d, e, f, g, h]) => [b, f, d, h, a, e, c, g]], | |
[-w, 0, ([a, b, c, d, e, f, g, h]) => [e, a, g, c, f, b, h, d]], | |
]; | |
const mapCubeFaces = ([net, instr, start, dim, w]) => { | |
const q = [ | |
[ | |
[net[0].findIndex(Boolean), 0], | |
[1, 2, 4, 8, 16, 32, 64, 128], | |
], | |
]; | |
const v = new Set(); | |
const faces = []; | |
while (q.length) { | |
const [[px, py], corners] = q.shift(); | |
q.push( | |
...DIR_ROT(w) | |
.map(([dx, dy, rot]) => [ | |
[px + dx, py + dy], | |
rot(corners), | |
]) | |
.filter( | |
([[x, y]]) => | |
net[y]?.[x] && | |
!v.has((y << 16) | x) && | |
v.add((y << 16) | x) | |
) | |
.filter(([xy, [a, b, c, d]]) => | |
faces.push([xy, [b | d, d | c, c | a, a | b]]) | |
) | |
); | |
} | |
return [net, instr, start, dim, w, faces]; | |
}; | |
const walkCubicEarth = ([net, instr, start, , w, faces]) => | |
instr.reduce(([p, f], [turn, steps]) => { | |
let facing = (f = (f + 4 + turn) % 4); | |
let pos, c; | |
while ((c = net[p[1]]?.[p[0]]) !== "#" && steps >= 0) { | |
if (c) { | |
pos = p; | |
facing = f; | |
steps--; | |
p = DIR[facing].map((d, i) => d + p[i]); | |
} else { | |
const face = faces.find(([coord]) => | |
coord.every((c, i) => c === pos[i] - (pos[i] % w)) | |
); | |
const edge = face[1][facing]; | |
const [newFacePos, newFace] = faces.find( | |
f => f !== face && f[1].includes(edge) | |
); | |
const newFacing = (newFace.indexOf(edge) + 2) % 4; | |
let [rx, ry] = p.map(v => v % w); | |
while (f !== newFacing) { | |
[rx, ry] = [w - 1 - ry, rx]; | |
f = (f + 1) % 4; | |
} | |
p = [rx, ry].map( | |
(v, i) => newFacePos[i] + ((w + v) % w) | |
); | |
} | |
} | |
return [pos, facing]; | |
}, start); | |
const score = ([[col, row], facing]) => | |
1000 * (row + 1) + 4 * (col + 1) + facing; | |
const regroup = input => | |
input | |
.split("\n\n") | |
.reduce((groups, e, i) => { | |
if (!groups[i >> 1]) groups.push([]); | |
groups[i >> 1].push(e); | |
return groups; | |
}, []) | |
.map(v => v.join("\n\n")); | |
export const part1 = pipe(parse, walkFlatEarth, score); | |
export const part2 = pipe( | |
parse, | |
mapCubeFaces, | |
walkCubicEarth, | |
score | |
); | |
export const part3 = pipe(regroup, map(part2), sum); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment