UNPKG

expeditaet

Version:
119 lines (108 loc) 3.96 kB
import { task } from '@alexaegis/advent-of-code-lib'; import { max, min } from '@alexaegis/advent-of-code-lib/math'; import { Direction, Vec3 } from '@alexaegis/advent-of-code-lib/model'; import packageJson from '../package.json'; import { Tile } from './p1.js'; import { parse } from './parse.js'; const ZT5 = [...Array.from({ length: 5 }).keys()]; const EMTPY_GEN = Array.from({ length: 5 }).map(() => Array.from({ length: 5 }).map(() => Tile.EMTPY), ); export const recursiveAdjacents = (x: number, y: number, d: number): Vec3[] => { const v = new Vec3(x, y, d); return Direction.cardinalDirections .map((dir) => v.add({ ...dir, z: 0 })) .flatMap((dir) => { if (dir.x < 0) { return [new Vec3(1, 2, d - 1)]; // The left from the middle one, one level below } else if (dir.x > 4) { return [new Vec3(3, 2, d - 1)]; // The right from the middle one, one level below } else if (dir.y < 0) { return [new Vec3(2, 1, d - 1)]; // The top from the middle one, one level below } else if (dir.y > 4) { return [new Vec3(2, 3, d - 1)]; // The bottom from the middle one, one level below } else if (dir.x === 2 && dir.y === 2) { // Points to the inner dimension, one level above if (v.x === 3) { return ZT5.map((i) => new Vec3(4, i, d + 1)); // Whole right side one level above } else if (v.x === 1) { return ZT5.map((i) => new Vec3(0, i, d + 1)); // Whole left side one level above } else if (v.y === 3) { return ZT5.map((i) => new Vec3(i, 4, d + 1)); // Whole bottom side one level above } else if (v.y === 1) { return ZT5.map((i) => new Vec3(i, 0, d + 1)); // Whole top side one level above } } return [dir]; }); }; export const isDie = (adj: Vec3[], map: Map<number, Tile[][]>): boolean => { return ( adj.map((a) => map.get(a.z)?.[a.y]?.[a.x] ?? Tile.EMTPY).filter((t) => t === Tile.BUG) .length !== 1 ); }; export const isBirth = (adj: Vec3[], map: Map<number, Tile[][]>): boolean => { const adjBugs = adj .map((a) => map.get(a.z)?.[a.y]?.[a.x] ?? Tile.EMTPY) .count((t) => t === Tile.BUG); return adjBugs === 1 || adjBugs === 2; }; const expand = (level: Map<number, Tile[][]>): void => { level.set([...level.keys()].reduce(min) - 1, EMTPY_GEN); level.set([...level.keys()].reduce(max) + 1, EMTPY_GEN); }; const shrink = (level: Map<number, Tile[][]>): void => { const lowKey = [...level.keys()].reduce(min); const low = level.get(lowKey); const highKey = [...level.keys()].reduce(max); const high = level.get(highKey); if (low && low.flat().count((t) => t === Tile.BUG) === 0) { level.delete(lowKey); } if (high && high.flat().count((t) => t === Tile.BUG) === 0) { level.delete(highKey); } }; export const p2 = (genTarget = 200) => (input: string): number => { let levels = new Map<number, Tile[][]>(); levels.set(0, parse(input) as Tile[][]); for (let gen = 0; gen < genTarget; gen++) { const nextLevels = new Map<number, Tile[][]>(); expand(levels); for (const [dimension, map] of levels.entries()) { const nextGen: Tile[][] = []; for (let y = 0; y < map.length; y++) { const row = map[y]; const nextRow: Tile[] = []; if (row) { for (let x = 0; x < map.length; x++) { if (x === 2 && y === 2) { nextRow[x] = Tile.EMTPY; } else { const tile = row[x]; if (tile) { const adj = recursiveAdjacents(x, y, dimension); if (tile === Tile.BUG && isDie(adj, levels)) { nextRow[x] = Tile.EMTPY; } else if (tile === Tile.EMTPY && isBirth(adj, levels)) { nextRow[x] = Tile.BUG; } else { nextRow[x] = tile; } } } } } nextGen[y] = nextRow; } nextLevels.set(dimension, nextGen); } levels = nextLevels; shrink(levels); } return [...levels.values()].flat(2).count((t) => t === Tile.BUG); }; await task(p2(), packageJson.aoc); // 2120 ~741ms