Advent of code

 12 décembre 2024 

  Garden Groups : Trouver des zones et calculer l'aire, le périmètre et le nombre de côtés.
UUUKKKKZZZZ
   
UUKKKKKZZZZ
   
UUKKKKKKKZZ
   
      
  1. code.py
  2. code_visualisation.py
  3. find_4_colors_coloring.py
  4. colorByLetter.png
  5. four_colors_plain.png
  6. multicolors_borders.png
  7. multicolors_plain.png
  8. four_colors_terminal_borders.png
with open("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 side
def find_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] = True
        for dx, dy in DIRECTIONS:     
            nx, ny = x+dx, y+dy
            if (nx,ny) not in region:    # only if not already processed
                if (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 = 0
    for 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)
            
    return len(region), len(borders), sides
            
            
#  [2,3,4, 10,11,12,13, 35, 100,101] would return 4
def calc_nb_of_continuous_segments(pos: list[int]) -> int:
    pos.sort()
    return 1 + len([1 for i in range(1, len(pos)) if pos[i] != pos[i-1]+1])
        
     
used = [W*[False] for i in range(H)]
price1 = price2 = 0
for y in range(H):
    for x in range(W):
        if not 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)