solve_day14 :: (test: bool) {
contents := read_entire_file(ifx test then "inputs/day14_test.txt" else "inputs/day14.txt");
lines := split(contents, cast(u8) #char "\n");
defer array_free(lines);
grid_min_x: s64 = S64_MAX;
grid_max_x: s64 = 0;
grid_y: s64 = 0;
wall_points: [..]Wall_Point;
for line: lines {
wall_point_splits := split(line, " -> ");
for wall_point_splits {
wall_point := parse_wall(it);
wall_point.next = wall_points.count;
array_add(*wall_points, wall_point);
grid_min_x = min(grid_min_x, wall_point.x);
grid_max_x = max(grid_max_x, wall_point.x);
grid_y = max(grid_y, wall_point.y);
}
wall_points[wall_points.count - 1].next = -1;
}
// Expand the grid
grid_min_x -= 135;
grid_max_x += 140;
grid_x_offset := 500 - grid_min_x;
grid_x := grid_max_x - grid_min_x;
grid_y += 2;
for *wall_points it.x -= grid_min_x;
grid: []u8 = NewArray(grid_x * grid_y, u8);
paint_grid(grid, grid_x, grid_y, wall_points);
part1 := 0;
part2 := 0;
fallen := 0;
while outer:= true {
sand_x := grid_x_offset;
sand_y := 0;
while true {
if grid[grid_x_offset] == #char "o" {
part2 = fallen;
break outer;
}
if (1 + sand_y) * grid_x + sand_x > grid.count {
print("Grid: %, %\n", grid_x, grid_y);
print("Sand: %, %\n", sand_x, sand_y);
}
assert(sand_x != 0 && sand_x != grid_x - 1, "Going out of bounds. X is % and grid width is between 0 and %.", sand_x, grid_x);
if grid[(1 + sand_y) * grid_x + sand_x] == #char "." {
sand_y += 1;
} else if grid[(1 + sand_y) * grid_x + sand_x - 1] == #char "." {
sand_y += 1;
sand_x -= 1;
} else if grid[(1 + sand_y) * grid_x + sand_x + 1] == #char "." {
sand_y += 1;
sand_x += 1;
} else {
grid[sand_y * grid_x + sand_x] = #char "o";
break;
}
if sand_y == grid_y - 1 {
if part1 == 0 part1 = fallen;
grid[sand_y * grid_x + sand_x] = #char "o";
break;
}
}
fallen += 1;
}
print("Part 1: %\n", part1);
print("Part 2: %\n", part2);
}
parse_wall :: (text: string) -> Wall_Point {
comma_index := find_index_from_left(text, cast(u8) #char ",");
first, first\_success := string_to_int(slice(text, 0, comma_index), 10, s64);
second, second_success := string_to_int(slice(text, comma_index + 1, text.count - comma_index - 1), 10, s64);
return .{
x = first,
y = second,
next = -1,
};
}
paint_grid :: (grid: []u8, width: s64, height: s64, walls: [..]Wall_Point) {
memset(grid.data, xx #char ".", grid.count);
i := 0;
while outer:= i < walls.count {
prev := walls[i];
while true {
defer i += 1;
if walls[i].x != prev.x {
min_x := min(walls[i].x, prev.x);
max_x := max(walls[i].x, prev.x);
for min_x..max_x {
grid[prev.y * width + it] = #char "#";
}
} else {
min_y := min(walls[i].y, prev.y);
max_y := max(walls[i].y, prev.y);
for min_y..max_y {
grid[it * width + prev.x] = #char "#";
}
}
if walls[i].next == -1 break;
prev = walls[i];
}
}
}
#scope_file
Wall_Point :: struct {
x: s64;
y: s64;
next: s64;
}