Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # aoc202214.py
- import pathlib
- import re
- import sys
- from typing import NamedTuple
- class Coordinate(NamedTuple):
- x: int
- y: int
- def parse(puzzle_input: str) -> list[list[Coordinate]]:
- """ Parse input """
- pattern = re.compile(r'\d+,\d+')
- string_paths: list[list[str]] = [
- re.findall(pattern, line) for line in puzzle_input.splitlines()
- ]
- solid_structures: list[list[Coordinate]] = []
- for struct in string_paths:
- coords: list[Coordinate] = []
- for coord in struct:
- x, y = coord.split(',')
- coords.append(Coordinate(int(x), int(y)))
- solid_structures.append(coords)
- return solid_structures
- def missing_values(beginning: int, final: int) -> list[int]:
- """ Return list of ints of missing values between start and end points """
- low: int = min(beginning, final)
- high: int = max(beginning, final)
- return list(range(low, high + 1))
- def get_line(start: Coordinate, end: Coordinate) -> list[Coordinate]:
- """ Get full set of coordinates assuming straight line """
- coords: list[Coordinate] = []
- if start.x == end.x:
- x = start.x
- y_values = missing_values(start.y, end.y)
- for y in y_values:
- coords.append(Coordinate(x, y))
- else:
- y = start.y
- x_values = missing_values(start.x, end.x)
- for x in x_values:
- coords.append(Coordinate(x, y))
- return coords
- def make_grid(paths: list[list[Coordinate]]) -> dict[Coordinate, str]:
- """ Make grid """
- grid: dict[Coordinate, str] = {}
- for path in paths:
- for idx, coord in enumerate(path):
- if idx == len(path) - 1:
- break
- coords: list[Coordinate] = get_line(coord, path[idx + 1])
- for coord in coords:
- grid[coord] = "#"
- return grid
- def move_sand(grid: dict[Coordinate, str],
- pos: Coordinate,
- overshoot: int) -> Coordinate:
- while True:
- next_pos = Coordinate(pos.x, pos.y + 1)
- if next_pos in grid:
- left_move = Coordinate(pos.x - 1, pos.y + 1)
- if left_move in grid:
- right_move = Coordinate(pos.x + 1, pos.y + 1)
- if right_move in grid:
- return pos
- else:
- return move_sand(grid, right_move, overshoot)
- else:
- return move_sand(grid, left_move, overshoot)
- elif next_pos.y > overshoot:
- return next_pos
- else:
- pos = next_pos
- def fill_sand(grid: dict[Coordinate, str],
- pos: Coordinate,
- floor: int) -> Coordinate:
- while True:
- next_pos = Coordinate(pos.x, pos.y + 1)
- if next_pos in grid:
- left_move = Coordinate(pos.x - 1, pos.y + 1)
- if left_move in grid:
- right_move = Coordinate(pos.x + 1, pos.y + 1)
- if right_move in grid:
- return pos
- else:
- return fill_sand(grid, right_move, floor)
- else:
- return fill_sand(grid, left_move, floor)
- elif next_pos.y > floor:
- return pos
- else:
- pos = next_pos
- def part1(data: list[list[Coordinate]]) -> int:
- """ Solve part 1 """
- grid: dict[Coordinate, str] = make_grid(data)
- source = Coordinate(500, 0)
- grid[source] = '+'
- units_of_sand: int = 0
- max_y: int = max(y for x, y in grid.keys())
- while True:
- sand: Coordinate = move_sand(grid, source, max_y)
- if sand.y > max_y:
- break
- grid[sand] = 'o'
- units_of_sand += 1
- return units_of_sand
- def part2(data: list[list[Coordinate]]) -> int:
- """ Solve part 2 """
- grid: dict[Coordinate, str] = make_grid(data)
- source = Coordinate(500, 0)
- grid[source] = '+'
- units_of_sand: int = 0
- max_y: int = max(y for x, y in grid.keys()) + 1
- while True:
- sand: Coordinate = fill_sand(grid, source, max_y)
- grid[sand] = 'o'
- units_of_sand += 1
- if sand == source:
- break
- return units_of_sand
- def solve(puzzle_input: str) -> tuple[int, int]:
- """ Solve the puzzle for the given input """
- data: list[list[Coordinate]] = parse(puzzle_input)
- solution1: int = part1(data) # Correct answer was 873 (with my data)
- solution2: int = part2(data) # Correct answer was 24813 (with my data)
- return solution1, solution2
- if __name__ == "__main__":
- for path in sys.argv[1:]:
- print(f"{path}:")
- puzzle_input = pathlib.Path(path).read_text().strip()
- solutions = solve(puzzle_input)
- print('\n'.join(str(solution) for solution in solutions))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement