solve_day23 :: (test:bool) {
contents := read_entire_file(ifx test then "inputs/day23_test.txt" else "inputs/day23.txt");
lines := split(contents, cast(u8) #char "\n");
max_rounds := 1500;
map_width := lines[0].count + max_rounds * 2;
map_height := lines.count + max_rounds * 2;
elves: [..]Elf;
map_current := NewArray(map_width * map_height, u8);
map_next := NewArray(map_width * map_height, u8);
memset(map_current.data, 0, map_current.count);
for line, line_index: lines {
for 0..line.count - 1 {
if line[it] == #char "#" {
elf := Elf.{ pos = .{ x = it + max_rounds, y = line_index + max_rounds } };
array_add(*elves, elf);
map_current[elf.pos.y * map_width + elf.pos.x] = 1;
}
}
}
directions := Direction.[
.{
p1 = .{ -1, -1 },
p2 = .{ 0, -1 },
p3 = .{ 1, -1 },
},
.{
p1 = .{ -1, 1 },
p2 = .{ 0, 1 },
p3 = .{ 1, 1 },
},
.{
p1 = .{ -1, 1 },
p2 = .{ -1, 0 },
p3 = .{ -1, -1 },
},
.{
p1 = .{ 1, -1 },
p2 = .{ 1, 0 },
p3 = .{ 1, 1 },
},
];
l := NewArray(map_width * map_height, u8);
memset(l.data, cast(u8) #char ".", l.count);
for elf: elves {
assert(l[elf.pos.y * map_width + elf.pos.x] != #char "#");
l[elf.pos.y * map_width + elf.pos.x] = #char "#";
}
look_at_elf := -2;
part1 := 0;
part2 := 0;
for round: 0..max_rounds {
no_move := 0;
memset(map_next.data, 0, map_width * map_height);
for *elf, elf_i: elves {
elf.maybe_move_to = elf.pos;
found := false;
for x: -1..1 {
for y: -1..1 {
if x == 0 && y == 0 continue;
if map_current[(elf.pos.y + y) * map_width + elf.pos.x + x] == 1 {
found = true;
break x;
}
}
}
if !found {
no_move += 1;
continue;
}
found = false;
if elf_i == look_at_elf print("%\n", map_current[(elf.pos.y - 1) * map_width + elf.pos.x]);
for 0..3 {
dir := directions[(round + it) % 4];
cell1 := map_current[(elf.pos.y + dir.p1.y) * map_width + elf.pos.x + dir.p1.x];
cell2 := map_current[(elf.pos.y + dir.p2.y) * map_width + elf.pos.x + dir.p2.x];
cell3 := map_current[(elf.pos.y + dir.p3.y) * map_width + elf.pos.x + dir.p3.x];
if elf_i == look_at_elf print("Round before: %, %, %\n", cell1, cell2, cell3);
if cell1 == 0 && cell2 == 0 && cell3 == 0 {
elf.maybe_move_to = elf.pos + dir.p2;
if elf_i == look_at_elf print("%, %\n", elf.pos, elf.maybe_move_to);
map_next[elf.maybe_move_to.y * map_width + elf.maybe_move_to.x] += 1;
found = true;
break;
}
}
if !found {
no_move += 1;
}
}
memset(map_current.data, 0, map_width * map_height);
for *elf, elf_i: elves {
if elf_i == look_at_elf print("%\n", elf.pos);
if map_next[elf.maybe_move_to.y * map_width + elf.maybe_move_to.x] == 1 {
elf.pos = elf.maybe_move_to;
}
map_current[elf.pos.y * map_width + elf.pos.x] = 1;
if elf_i == look_at_elf print("%\n", elf.pos);
}
if round == 9 {
max_on_map: Vec2 = .{ 0, 0 };
min_on_map: Vec2 = .{ map_width, map_height };
for elves {
min_on_map.x = min(min_on_map.x, it.pos.x);
min_on_map.y = min(min_on_map.y, it.pos.y);
max_on_map.x = max(max_on_map.x, it.pos.x);
max_on_map.y = max(max_on_map.y, it.pos.y);
}
part1 = (max_on_map.x - min_on_map.x + 1) * (max_on_map.y - min_on_map.y + 1) - elves.count;
}
if no_move == elves.count {
part2 = round + 1;
break;
}
}
print("Part 1: %\n", part1);
print("Part 2: %\n", part2);
}
#scope_file
Vec2 :: struct {
x: s64;
y: s64;
}
operator + :: (v1: Vec2, v2: Vec2) -> Vec2 {
return .{ x = v1.x + v2.x, y = v1.y + v2.y };
}
Elf :: struct {
pos: Vec2;
maybe_move_to: Vec2;
}
Cell :: struct {
round: s8;
count: s8;
}
Direction :: struct {
p1: Vec2;
p2: Vec2;
p3: Vec2;
}