Skip to content

Instantly share code, notes, and snippets.

@bluepichu
Created December 18, 2022 05:12
Show Gist options
  • Save bluepichu/62728171f54823401e365c7aef4dd605 to your computer and use it in GitHub Desktop.
Save bluepichu/62728171f54823401e365c7aef4dd605 to your computer and use it in GitHub Desktop.
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