#import "Basic";
#import "File";
#import "String";
solve_day14 :: (test: bool) {
contents := read_entire_file(ifx test then "inputs/day14_test.txt" else "inputs/day14.txt");
lines := split(contents, "\n");
grid_width := lines[0].count;
part1 := 0;
part2 := 0;
history: [..]Grid;
builder: String_Builder;
for lines {
assert(it.count == grid_width, "it.count != grid_width");
print_to_builder(*builder, it);
}
grid_contents := builder_to_string(*builder);
grid := Grid.{
grid = grid_contents,
width = grid_width,
height = grid_contents.count / grid_width,
};
assert(grid.grid.count % grid.height == 0, "grid.grid.count % grid.height != 0");
total_cycles := 1_000_000_000;
cycle_length := 0;
cycle_start := 0;
tilt(.NORTH, grid);
part1 = xx calc(grid);
tilt(.WEST, grid);
tilt(.SOUTH, grid);
tilt(.EAST, grid);
array_add(*history, copy(grid));
for outer: 1..total_cycles {
tilt(.NORTH, grid);
tilt(.WEST, grid);
tilt(.SOUTH, grid);
tilt(.EAST, grid);
array_add(*history, copy(grid));
for history {
if it_index + 1 == history.count {
break;
}
if it == grid {
cycle_length = outer - it_index;
cycle_start = it_index + 1;
break outer;
}
}
}
assert(cycle_start != 0 && cycle_length != 0, "Cycle start: %, cycle length: %", cycle_start, cycle_length);
last_grid_index := cycle_start + (total_cycles - cycle_start) % cycle_length;
last_grid := history[last_grid_index - 1];
part2 = xx calc(last_grid);
print("Part 1: %\n", part1);
print("Part 2: %\n", part2);
}
operator == :: (g1: Grid, g2: Grid) -> bool {
assert(g1.height == g2.height);
assert(g1.width == g2.width);
for 0..g1.height - 1 {
if slice(g1.grid, it * g1.width, g1.width) != slice(g2.grid, it * g2.width, g2.width) {
return false;
}
}
return true;
}
copy :: (grid: Grid) -> Grid {
return .{
width = grid.width,
height = grid.height,
grid = copy_string(grid.grid),
};
}
print_grid :: (grid: Grid) {
print("--------\n");
for 0..grid.height - 1 {
print("%\n", slice(grid.grid, grid.width * it, grid.width));
}
}
calc :: (grid: Grid) -> u64 {
result: u64 = 0;
for row: 0..grid.height - 1 {
for column: 0..grid.width - 1 {
if grid.grid[row * grid.width + column] == #char "O" {
result += xx (grid.height - row);
}
}
}
return result;
}
tilt :: (dir: Tilt_Direction, grid: Grid) {
if dir == {
case .NORTH;
tilt_north(grid);
case .SOUTH;
tilt_south(grid);
case .WEST;
tilt_west(grid);
case .EAST;
tilt_east(grid);
}
}
tilt_south :: (grid: Grid) {
for r: 1..grid.height - 1 {
row := grid.height - 1 - r;
for column: 0..grid.width - 1 {
if grid.grid[row * grid.width + column] == #char "O" {
t := row;
while t < grid.height - 1 {
defer t += 1;
if grid.grid[(t + 1) * grid.width + column] == #char "." {
grid.grid[(t + 1) * grid.width + column] = #char "O";
grid.grid[t * grid.width + column] = #char ".";
} else {
break;
}
}
}
}
}
}
tilt_east :: (grid: Grid) {
for c: 1..grid.width - 1 {
column := grid.width - 1 - c;
for row: 0..grid.height - 1 {
if grid.grid[row * grid.width + column] == #char "O" {
t := column;
while t < grid.width - 1 {
defer t += 1;
if grid.grid[row * grid.width + t + 1] == #char "." {
grid.grid[row * grid.width + t + 1] = #char "O";
grid.grid[row * grid.width + t] = #char ".";
} else {
break;
}
}
}
}
}
}
tilt_north :: (grid: Grid) {
for row: 1..grid.height - 1 {
for column: 0..grid.width - 1 {
if grid.grid[row * grid.width + column] == #char "O" {
t := row;
while t > 0 {
defer t -= 1;
if grid.grid[(t - 1) * grid.width + column] == #char "." {
grid.grid[(t - 1) * grid.width + column] = #char "O";
grid.grid[t * grid.width + column] = #char ".";
} else {
break;
}
}
}
}
}
}
tilt_west :: (grid: Grid) {
for column: 1..grid.width - 1 {
for row: 0..grid.height - 1 {
if grid.grid[row * grid.width + column] == #char "O" {
t := column;
while t > 0 {
defer t -= 1;
if grid.grid[row * grid.width + t - 1] == #char "." {
grid.grid[row * grid.width + t - 1] = #char "O";
grid.grid[row * grid.width + t] = #char ".";
} else {
break;
}
}
}
}
}
}
Tilt_Direction :: enum {
NORTH;
EAST;
SOUTH;
WEST;
}