Skip to content

Commit

Permalink
feat: 2023 Day 22
Browse files Browse the repository at this point in the history
  • Loading branch information
mfulton26 committed Dec 25, 2023
1 parent ae6a683 commit b8b4642
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 0 deletions.
16 changes: 16 additions & 0 deletions 2023/day/22/part/1/solve.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import solve from "./solve.ts";

import { assertEquals } from "../../../../../lib/testing/asserts.ts";

Deno.test("example", () => {
const input = `\
1,0,1~1,2,1
0,0,2~2,0,2
0,2,3~2,2,3
0,0,4~0,2,4
2,0,5~2,2,5
0,1,6~2,1,6
1,1,8~1,1,9`;

assertEquals(solve(input), 5);
});
68 changes: 68 additions & 0 deletions 2023/day/22/part/1/solve.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
type Vector = { x: number; y: number; z: number };
type Brick = { label: string; bottomLeft: Vector; topRight: Vector };

export default function solve(input: string) {
const bricks = input.split("\n").map<Brick>((line, index) => {
const label = String.fromCharCode("A".charCodeAt(0) + index);
const [a, b] = line.split("~").map((word) => {
const [x, y, z] = word.split(",").map(Number);
return { x, y, z };
});
return {
label,
bottomLeft: {
x: Math.min(a.x, b.x),
y: Math.min(a.y, b.y),
z: Math.min(a.z, b.z),
},
topRight: {
x: Math.max(a.x, b.x),
y: Math.max(a.y, b.y),
z: Math.max(a.z, b.z),
},
};
});
const bricksInFront = new Map<number, Map<number, Brick>>();
bricks.sort(({ bottomLeft: { z: a } }, { bottomLeft: { z: b } }) => a - b);
const dependencies = bricks.reduce(
(map, brick) => map.set(brick, new Set<Brick>()),
new Map<Brick, Set<Brick>>(),
);
const dependents = bricks.reduce(
(map, brick) => map.set(brick, new Set<Brick>()),
new Map<Brick, Set<Brick>>(),
);
for (const brick of bricks) {
let falling = true;
while (falling && brick.bottomLeft.z > 1) {
for (let y = brick.bottomLeft.y; y <= brick.topRight.y; y++) {
if (!bricksInFront.has(y)) bricksInFront.set(y, new Map());
const row = bricksInFront.get(y)!;
for (let x = brick.bottomLeft.x; x <= brick.topRight.x; x++) {
const brickBehind = row.get(x);
if (brickBehind === undefined) continue;
if (brick.bottomLeft.z - 1 > brickBehind.topRight.z) continue;
falling = false;
dependencies.get(brick)!.add(brickBehind);
dependents.get(brickBehind)!.add(brick);
}
}
if (falling) brick.bottomLeft.z--, brick.topRight.z--;
}
for (let y = brick.bottomLeft.y; y <= brick.topRight.y; y++) {
if (!bricksInFront.has(y)) bricksInFront.set(y, new Map());
const row = bricksInFront.get(y)!;
for (let x = brick.bottomLeft.x; x <= brick.topRight.x; x++) {
row.set(x, brick);
}
}
}
return bricks
.filter((brick) => {
for (const dependent of dependents.get(brick)!) {
if (dependencies.get(dependent)!.size === 1) return false;
}
return true;
})
.length;
}
16 changes: 16 additions & 0 deletions 2023/day/22/part/2/solve.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import solve from "./solve.ts";

import { assertEquals } from "../../../../../lib/testing/asserts.ts";

Deno.test("example", () => {
const input = `\
1,0,1~1,2,1
0,0,2~2,0,2
0,2,3~2,2,3
0,0,4~0,2,4
2,0,5~2,2,5
0,1,6~2,1,6
1,1,8~1,1,9`;

assertEquals(solve(input), 7);
});
76 changes: 76 additions & 0 deletions 2023/day/22/part/2/solve.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
type Vector = { x: number; y: number; z: number };
type Brick = { label: string; bottomLeft: Vector; topRight: Vector };

export default function solve(input: string) {
const bricks = input.split("\n").map<Brick>((line, index) => {
const label = String.fromCharCode("A".charCodeAt(0) + index);
const [a, b] = line.split("~").map((word) => {
const [x, y, z] = word.split(",").map(Number);
return { x, y, z };
});
return {
label,
bottomLeft: {
x: Math.min(a.x, b.x),
y: Math.min(a.y, b.y),
z: Math.min(a.z, b.z),
},
topRight: {
x: Math.max(a.x, b.x),
y: Math.max(a.y, b.y),
z: Math.max(a.z, b.z),
},
};
});
const bricksInFront = new Map<number, Map<number, Brick>>();
bricks.sort(({ bottomLeft: { z: a } }, { bottomLeft: { z: b } }) => a - b);
const dependencies = bricks.reduce(
(map, brick) => map.set(brick, new Set<Brick>()),
new Map<Brick, Set<Brick>>(),
);
const dependents = bricks.reduce(
(map, brick) => map.set(brick, new Set<Brick>()),
new Map<Brick, Set<Brick>>(),
);
for (const brick of bricks) {
let falling = true;
while (falling && brick.bottomLeft.z > 1) {
for (let y = brick.bottomLeft.y; y <= brick.topRight.y; y++) {
if (!bricksInFront.has(y)) bricksInFront.set(y, new Map());
const row = bricksInFront.get(y)!;
for (let x = brick.bottomLeft.x; x <= brick.topRight.x; x++) {
const brickBehind = row.get(x);
if (brickBehind === undefined) continue;
if (brick.bottomLeft.z - 1 > brickBehind.topRight.z) continue;
falling = false;
dependencies.get(brick)!.add(brickBehind);
dependents.get(brickBehind)!.add(brick);
}
}
if (falling) brick.bottomLeft.z--, brick.topRight.z--;
}
for (let y = brick.bottomLeft.y; y <= brick.topRight.y; y++) {
if (!bricksInFront.has(y)) bricksInFront.set(y, new Map());
const row = bricksInFront.get(y)!;
for (let x = brick.bottomLeft.x; x <= brick.topRight.x; x++) {
row.set(x, brick);
}
}
}
let sum = -0;
for (const brick of bricks) {
const fallenBricks = new Set<Brick>().add(brick);
for (const fallenBrick of fallenBricks) {
falling: for (const dependent of dependents.get(fallenBrick)!) {
const dependentDependencies = dependencies.get(dependent)!;
for (const dependentDependency of dependentDependencies) {
if (fallenBricks.has(dependentDependency)) continue;
continue falling;
}
fallenBricks.add(dependent);
}
}
sum += fallenBricks.size - 1;
}
return sum;
}

0 comments on commit b8b4642

Please sign in to comment.