Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions puzzles/solutions/2025/d04/p1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import itertools
import sys

example_input = """
..@@.@@@@.
@@@.@.@.@@
@@@@@.@.@@
@.@@@@..@.
@@.@@@@.@@
.@@@@@@@.@
.@.@.@.@@@
@.@@@.@@@@
.@@@@@@@@.
@.@.@@@.@.
""".strip()

PAPER_ROLL = "@"
MAX_ADJACENT_PAPER_ROLLS = 3

Grid = list[list[str]]
Position = tuple[int, int]


def get_grid(input_text: str) -> Grid:
return [list(line) for line in input_text.splitlines()]


def get_adjacent_rolls_number(grid: Grid, row: int, column: int):
min_row = max(row - 1, 0)
max_row = min(row + 1, len(grid) - 1)
min_column = max(column - 1, 0)
max_column = min(column + 1, len(grid[0]) - 1)
return (
sum(
grid[current_row][current_column] == PAPER_ROLL
for current_row, current_column in itertools.product(
range(min_row, max_row + 1), range(min_column, max_column + 1)
)
)
# Exclude the cell we're counting adjacent around.
- (grid[row][column] == PAPER_ROLL)
)


def get_accessible_rolls(grid: Grid) -> list[Position]:
return [
(row, column)
for row, column in itertools.product(range(len(grid)), range(len(grid[0])))
if (
grid[row][column] == PAPER_ROLL
and get_adjacent_rolls_number(grid, row, column) <= MAX_ADJACENT_PAPER_ROLLS
)
]


def get_answer(input_text: str):
grid = get_grid(input_text)
return len(get_accessible_rolls(grid))


if __name__ == "__main__":
puzzle_input = sys.argv[1] if len(sys.argv) > 1 else example_input
print(get_answer(puzzle_input))
29 changes: 29 additions & 0 deletions puzzles/solutions/2025/d04/p2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import sys

import p1

EMPTY_CELL = "."
Comment thread
katzuv marked this conversation as resolved.


def clean_accessed_rolls(
grid: p1.Grid, accessible_rolls_positions: list[p1.Position]
) -> None:
for row, column in accessible_rolls_positions:
grid[row][column] = EMPTY_CELL


def get_answer(input_text: str):
grid = p1.get_grid(input_text)
total_accessible_rolls = 0
while True:
accessible_rolls = p1.get_accessible_rolls(grid)
if not accessible_rolls:
break
total_accessible_rolls += len(accessible_rolls)
Comment thread
katzuv marked this conversation as resolved.
clean_accessed_rolls(grid, accessible_rolls)
return total_accessible_rolls


if __name__ == "__main__":
puzzle_input = sys.argv[1] if len(sys.argv) > 1 else p1.example_input
print(get_answer(puzzle_input))