2022-12-14 - Regolith Reservoir
(original .ipynb)
Day 14 puzzle input is a sequence of "->"-separated point pairs which describe rock formations (mine is here). Part 1 dropping grains of sand from a given point, until the sand overflows and drops off to "the abyss". Part two involves assuming there is no abyss, but an infinitely wide floor 2 rows below the lowest rock and pouring sand in until it builds up to the top and finding how many grains this takes.
puzzle_input_str = open("./puzzle_input/day14.txt").read()
test_input_str = """498,4 -> 498,6 -> 496,6
503,4 -> 502,4 -> 502,9 -> 494,9"""
def parse_point(point_str):
col, row = point_str.split(",")
return int(row), int(col)
def parse_line(line):
return [parse_point(point) for point in line.split(" -> ")]
def draw_line(grid, point1, point2):
from_point = min(point1, point2)
to_point = max(point1, point2)
from_row, from_col = from_point
to_row, to_col = to_point
for row in range(from_row, to_row+1):
for col in range(from_col, to_col+1):
grid[row][col] = "#"
def build_grid(shapes, with_floor=False):
max_row, max_col = 0, 0
for shape in shapes:
for row, col in shape:
max_row = max(max_row, row)
max_col = max(max_col, col)
max_col *= 2 # why not
grid = []
for row in range(max_row+1):
grid.append(["." for _ in range(max_col+1)])
for shape in shapes:
point = shape[0]
for next_point in shape[1:]:
draw_line(grid, point, next_point)
point = next_point
if with_floor:
grid.append(["." for _ in range(max_col+1)])
grid.append(["#" for _ in range(max_col+1)])
return grid
def add_sand(grid):
r, c = 0, 500
directions = ((1, 0), (1, -1), (1, 1))
moved = True
while moved:
if r+1 == len(grid):
return False
moved = False
for dr, dc in directions:
if grid[r+dr][c+dc] == ".":
r += dr
c += dc
moved = True
break
grid[r][c] = "o"
return True
def part_one(input_str):
shapes = [parse_line(line) for line in input_str.splitlines()]
grid = build_grid(shapes)
sand = 0
while add_sand(grid):
sand += 1
return sand
assert 24 == part_one(test_input_str)
print("part one:", part_one(puzzle_input_str))
part one: 674
def add_sand(grid):
r, c = 0, 500
directions = ((1, 0), (1, -1), (1, 1))
moved = True
while moved:
moved = False
for dr, dc in directions:
if r+1 < len(grid) and grid[r+dr][c+dc] == ".":
r += dr
c += dc
moved = True
break
if r == 0 and not moved:
return False
grid[r][c] = "o"
return True
def part_two(input_str):
shapes = [parse_line(line) for line in input_str.splitlines()]
grid = build_grid(shapes, True)
sand = 1
while add_sand(grid):
sand += 1
return sand
assert 93 == part_two(test_input_str)
print("part two:", part_two(puzzle_input_str))
part two: 24958