mirror of
https://github.com/thib8956/advent-of-code.git
synced 2025-08-24 00:11:57 +00:00
chore: create new project structure and aoc.py runner script
This commit is contained in:
117
adventofcode/2020/day11/rules.py
Normal file
117
adventofcode/2020/day11/rules.py
Normal file
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env python3
|
||||
from itertools import count, takewhile
|
||||
|
||||
directions = (
|
||||
(-1, -1),
|
||||
(-1, 0),
|
||||
(-1, 1),
|
||||
(0, -1),
|
||||
(0, 1),
|
||||
(1, -1),
|
||||
(1, 0),
|
||||
(1, 1),
|
||||
)
|
||||
|
||||
grid_width = 98
|
||||
grid_height = 97
|
||||
|
||||
|
||||
def handle_empty(index, grid, next_grid):
|
||||
"""
|
||||
If a seat is empty (L) and there are no occupied seats adjacent to it, the seat becomes occupied.
|
||||
"""
|
||||
neighbors = count_neighbors(index, grid)
|
||||
if neighbors == 0:
|
||||
next_grid[index] = "#"
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def handle_occupied(index, grid, next_grid):
|
||||
"""
|
||||
If a seat is occupied (#) and four or more seats adjacent to it are also occupied, the seat becomes empty.
|
||||
"""
|
||||
neighbors = count_neighbors(index, grid)
|
||||
if neighbors >= 4:
|
||||
next_grid[index] = "L"
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def count_neighbors(pos, grid):
|
||||
neighbors = 0
|
||||
x = pos % grid_width
|
||||
y = pos // grid_width
|
||||
for (dx, dy) in directions:
|
||||
xx = x + dx
|
||||
yy = y + dy
|
||||
if not in_bounds((xx, yy)):
|
||||
continue
|
||||
|
||||
if grid[yy * grid_width + xx] == "#":
|
||||
neighbors += 1
|
||||
return neighbors
|
||||
|
||||
|
||||
def handle_empty_2(index, grid, next_grid):
|
||||
"""
|
||||
If a seat is empty and there are no occupied seat visible in neither direction,
|
||||
the seat becomes occupied
|
||||
"""
|
||||
neighbors = 0
|
||||
x = index % grid_width
|
||||
y = index // grid_width
|
||||
for direction in directions:
|
||||
# keep moving in the specified direction, while checking
|
||||
# that we are in bounds of the grid
|
||||
for xx, yy in takewhile(in_bounds, move(x, y, direction)):
|
||||
cell = grid[yy * grid_width + xx]
|
||||
if cell == "#":
|
||||
neighbors += 1
|
||||
elif cell == "L":
|
||||
break # No occupied seat in that direction, we can break
|
||||
|
||||
if neighbors == 0:
|
||||
next_grid[index] = "#"
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def handle_occupied_2(index, grid, next_grid):
|
||||
"""
|
||||
An occupied seat becomes empty if there are five or more visible occupied
|
||||
seats in either direction.
|
||||
"""
|
||||
occupied = 0
|
||||
x = index % grid_width
|
||||
y = index // grid_width
|
||||
for direction in directions:
|
||||
for xx, yy in takewhile(in_bounds, move(x, y, direction)):
|
||||
cell = grid[yy * grid_width + xx]
|
||||
if cell == "#":
|
||||
occupied += 1
|
||||
elif cell != ".":
|
||||
break
|
||||
|
||||
if occupied >= 5:
|
||||
next_grid[index] = "L"
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def in_bounds(pos):
|
||||
x, y = pos
|
||||
return 0 <= x < grid_width and 0 <= y < grid_height
|
||||
|
||||
|
||||
def move(x, y, direction):
|
||||
xx = x
|
||||
yy = y
|
||||
while True:
|
||||
yield xx, yy
|
||||
xx += direction[0]
|
||||
yy += direction[1]
|
||||
|
||||
|
||||
part1_rules = {"L": handle_empty, "#": handle_occupied}
|
||||
part2_rules = {"L": handle_empty_2, "#": handle_occupied_2}
|
Reference in New Issue
Block a user