withopen("input.txt", 'r', encoding='utf-8') as f:
grid = [line[:-1] for line in f.readlines()]
W = len(grid[0])
H = len(grid)
# Returns area, perimeter, number of sidedeffind_region_stats(x, y, used) -> (int, int, int):
region = set()
borders = set()
region_letter = grid[y][x]
to_do = { (x,y), }
DIRECTIONS = ((1,0), (0,1), (-1,0), (0,-1))
# calculate interior and borders (for part 1)while to_do:
x, y = to_do.pop()
region.add((x,y))
used[y][x] = Truefor dx, dy in DIRECTIONS:
nx, ny = x+dx, y+dy
if (nx,ny) notin region: # only if not already processedif (0 <= nx < W) and (0 <= ny < H) and (grid[ny][nx] == region_letter) :
to_do.add((nx,ny))
else:
borders.add( ((x,y), (dx,dy)) )
# calculate number of sides (for part 2)
sides = 0for dx, dy in DIRECTIONS:
places_with_border_in_that_direction = [ pos for (pos, d) in borders if d == (dx, dy) ]
vertical = (dx == 0)
lines_with_border_in_that_direction = set( (y if vertical else x) for x,y in places_with_border_in_that_direction)
for line_coordinate in lines_with_border_in_that_direction:
if vertical:
coords_of_border_on_that_line = [ x for x,y in places_with_border_in_that_direction if y == line_coordinate]
else:
coords_of_border_on_that_line = [ y for x,y in places_with_border_in_that_direction if x == line_coordinate]
sides += calc_nb_of_continuous_segments(coords_of_border_on_that_line)
returnlen(region), len(borders), sides
# [2,3,4, 10,11,12,13, 35, 100,101] would return 4defcalc_nb_of_continuous_segments(pos: list[int]) -> int:
pos.sort()
return1 + len([1for i inrange(1, len(pos)) if pos[i] != pos[i-1]+1])
used = [W*[False] for i inrange(H)]
price1 = price2 = 0for y inrange(H):
for x inrange(W):
ifnot used[y][x]: # not already processed
area, perimeter, sides = find_region_stats(x, y, used)
price1 += area * perimeter
price2 += area * sides
print("Réponse partie 1:", price1)
print("Réponse partie 2:", price2)