#import "Basic";
#import "File";
#import "Math";
#import "Sort";
#import "String";
#import "Hash_Table";
solve_day22 :: (test: bool) {
input := read_entire_file("inputs/day22.txt");
lines := split(input, "\n");
bricks: [..]Brick;
supports: Table(s64, [..]s64);
supported_by: Table(s64, [..]s64);
for lines {
brick := parse_brick(it);
brick.label = bricks.count;
array_add(*bricks, brick);
}
quick_sort(bricks, (b1, b2) => b1.min.z - b2.min.z);
settle(bricks);
find_supports(bricks, *supports, *supported_by);
part1, part2 := solve2(bricks, supports, supported_by);
print("Part 1: %\nPart 2: %\n", part1, part2);
//print("Part 1: %\n", solve1(*bricks));
}
solve2 :: (bricks: [..]Brick, supports: Table(s64, [..]s64), supported_by: Table(s64, [..]s64)) -> part1: s64, part2: s64 {
part2 := 0;
part1 := 0;
for firstDisintegrated: 0..bricks.count - 1 {
dummy_void: void;
moved: Table(s64, void);
table_add(*moved, firstDisintegrated, dummy_void);
moreMoved := true;
while moreMoved {
moreMoved = false;
for mightMove: 0..bricks.count - 1 {
if table_contains(*moved, mightMove) || bricks[mightMove].min.z == 1 continue;
supp,found_supp := table_find(*supported_by, mightMove);
still_supported := false;
if found_supp {
for supp {
if !table_contains(*moved, it) {
still_supported = true;
break;
}
}
}
if !still_supported {
table_add(*moved, mightMove, dummy_void);
moreMoved = true;
}
}
}
table_remove(*moved, firstDisintegrated);
part2 += moved.count;
if !moved.count part1 += 1;
}
return part1, part2;
}
find_supports :: (bricks: [..]Brick, supports: *Table(s64, [..]s64), supported_by: *Table(s64, [..]s64)) {
for brick: 0..bricks.count - 1 {
for other: 0..bricks.count - 1 {
if brick == other continue;
if blocks(bricks[other], bricks[brick]) {
supports_array := table_find_pointer(supports, other);
supported_by_array := table_find_pointer(supported_by, brick);
dummy: void;
if !supports_array {
a: [..]s64;
supports_array = table_add(supports, other, a);
}
if !supported_by_array {
a: [..]s64;
supported_by_array = table_add(supported_by, brick, a);
}
array_add(supports_array, brick);
array_add(supported_by_array, other);
}
}
}
}
settle :: (bricks: [..]Brick) {
moved: bool = true;
while moved {
moved = false;
bubble_sort(bricks, (b1, b2) => b1.min.z - b2.min.z);
for *moveCand: bricks {
if moveCand.min.z == 1 {
continue;
}
can_move := true;
for blockCand: bricks {
if moveCand.label == blockCand.label continue;
if blocks(blockCand, moveCand) {
can_move = false;
break;
}
}
if can_move {
moveCand.min.z -= 1;
moveCand.max.z -= 1;
moved = true;
}
}
}
}
solve1 :: (bricks: *[..]Brick) -> s64 {
result: s64 = 0;
return result;
}
blocks :: (other: Brick, brick: Brick) -> bool {
if brick.min.z != other.max.z + 1 return false;
for x: other.min.x..other.max.x {
for y: other.min.y..other.max.y {
if x >= brick.min.x && x <= brick.max.x &&
y >= brick.min.y && y <= brick.max.y {
return true;
}
}
}
return false;
}
parse_brick :: (line: string) -> Brick {
ends := split(line, "~");
first_numbers := split(ends[0], ",");
second_numbers := split(ends[1], ",");
brick: Brick = ---;
x1,_ := string_to_int(first_numbers[0], 10, s64);
y1,_ := string_to_int(first_numbers[1], 10, s64);
z1,_ := string_to_int(first_numbers[2], 10, s64);
x2,_ := string_to_int(second_numbers[0], 10, s64);
y2,_ := string_to_int(second_numbers[1], 10, s64);
z2,_ := string_to_int(second_numbers[2], 10, s64);
return .{
label = 0,
min = .{
x = min(x1, x2),
y = min(y1, y2),
z = min(z1, z2),
},
max = .{
x = max(x1, x2),
y = max(y1, y2),
z = max(z1, z2),
},
};
}
overlap :: (b1: Brick, b2: Brick) -> bool {
return max(b1.min.x, b2.min.x) <= min(b1.max.x, b2.max.x) &&
max(b1.min.y, b2.min.y) <= min(b1.max.y, b2.max.y);
}
Brick :: struct {
label: s64;
min: Coord;
max: Coord;
}
operator == :: (b1: Brick, b2: Brick) -> bool {
return b1.min == b2.min && b1.max == b2.max;
}
operator == :: (c1: Coord, c2: Coord) -> bool {
return c1.x == c2.x && c1.y == c2.y && c1.z == c2.z;
}
print_brick :: (brick: Brick) {
print("%,%,%~%,%,%", brick.min.x, brick.min.y, brick.min.z, brick.max.x, brick.max.y, brick.max.z);
}
#scope_file
Coord :: struct {
x: s64;
y: s64;
z: s64;
}