Created
December 18, 2022 05:12
-
-
Save bluepichu/62728171f54823401e365c7aef4dd605 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 { Advent, f, fm, chr, ord } from "advent"; | |
import { Set, Map, ValueObject } from "immutable"; | |
const { compute, computeCheck } = await Advent({ day: 18 }); | |
class Point implements ValueObject { | |
public constructor( | |
public x: number, | |
public y: number, | |
public z: number | |
) { } | |
public* neighbors(): Iterable<Point> { | |
for (let dx = -1; dx <= 1; dx++) { | |
for (let dy = -1; dy <= 1; dy++) { | |
for (let dz = -1; dz <= 1; dz++) { | |
if (Math.abs(dx) + Math.abs(dy) + Math.abs(dz) === 1) { | |
yield new Point(this.x + dx, this.y + dy, this.z + dz); | |
} | |
} | |
} | |
} | |
} | |
public equals(other: Point): boolean { | |
return this.x === other.x && this.y === other.y && this.z === other.z; | |
} | |
public hashCode(): number { | |
return this.x * 1000000 + this.y * 1000 + this.z; | |
} | |
} | |
compute(2, async (input) => { | |
const data = input.parse(f.nl(f.cl(f.int()))); | |
let points = Set<Point>(); | |
for (let [x, y, z] of data) { | |
points = points.add(new Point(x, y, z)); | |
} | |
let ans = 0; | |
let missing = Set<Point>(); | |
for (let point of points) { | |
for (let neighbor of point.neighbors()) { | |
if (!points.has(neighbor)) { | |
ans++; | |
missing = missing.add(neighbor); | |
} | |
} | |
} | |
let minX = points.minBy(p => p.x)!.x; | |
let maxX = points.maxBy(p => p.x)!.x; | |
let minY = points.minBy(p => p.y)!.y; | |
let maxY = points.maxBy(p => p.y)!.y; | |
let minZ = points.minBy(p => p.z)!.z; | |
let maxZ = points.maxBy(p => p.z)!.z; | |
for (let point of missing) { | |
if (points.has(point)) { | |
continue; | |
} | |
// console.log("checking", point); | |
let seen = Set.of(point); | |
let queue = [point]; | |
let interior = true; | |
outer: while (queue.length > 0) { | |
let next = queue.shift()!; | |
for (let neighbor of next.neighbors()) { | |
if (neighbor.x < minX || neighbor.x > maxX || neighbor.y < minY || neighbor.y > maxY || neighbor.z < minZ || neighbor.z > maxZ) { | |
interior = false; | |
break outer; | |
} | |
if (points.has(neighbor)) { | |
continue; | |
} | |
if (!seen.has(neighbor)) { | |
seen = seen.add(neighbor); | |
queue.push(neighbor); | |
} | |
} | |
} | |
if (interior) { | |
points = points.union(seen); | |
} | |
} | |
ans = 0; | |
missing = Set<Point>(); | |
for (let point of points) { | |
for (let neighbor of point.neighbors()) { | |
if (!points.has(neighbor)) { | |
ans++; | |
missing.add(neighbor); | |
} | |
} | |
} | |
return ans; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment