#!/usr/bin/env python3 import sys input_file = sys.argv[1] with open(input_file) as fd: lines = [line.rstrip() for line in fd.readlines()] height = len(lines) width = len(lines[0]) visited: set[tuple[int, int]] = set() directions = [ (0, 1), (0, -1), (1, 0), (-1, 0), ] def get_region( pos: tuple[int, int], region: set[tuple[int, int]] ) -> set[tuple[int, int]]: region.add(pos) i, j = pos ochar = lines[i][j] for direction in directions: i, j = pos[0] + direction[0], pos[1] + direction[1] if i not in range(height) or j not in range(width): continue if (i, j) in region: continue char = lines[i][j] if char != ochar: continue region |= get_region((i, j), region) return region # def get_sides(region: set[tuple[int, int]]) -> int: # peri = 0 # for axis in (0, 1): # oaxis = 0 if axis else 1 # iss = set([pos[axis] for pos in region]) # sta: set[int] = set() # sto: set[int] = set() # for i in iss: # line = [pos[oaxis] for pos in region if pos[axis] == i] # line.sort() # last_j = None # for j in line: # if last_j is None: # sta.add(j) # elif last_j == j - 1: # pass # else: # sta.add(j) # sto.add(last_j) # last_j = j # if last_j is not None: # sto.add(last_j) # peri += len(sta) + len(sto) # return peri def get_perimeter(region: set[tuple[int, int]]) -> int: peri = 0 for axis in (0, 1): oaxis = 0 if axis else 1 iss = set([pos[axis] for pos in region]) for dire in (-1, 1): print(47, axis, dire, iss, peri) for i in iss: oi = i + dire line = [pos[oaxis] for pos in region if pos[axis] == i] line.sort() # last_j = None for j in line: if not axis: opos = oi, j else: opos = j, oi if opos in region: continue peri += 1 return peri def get_sides(region: set[tuple[int, int]]) -> int: peri = 0 for axis in (0, 1): oaxis = 0 if axis else 1 iss = set([pos[axis] for pos in region]) for dire in (-1, 1): print(47, axis, dire, iss, peri) for i in iss: oi = i + dire line = [pos[oaxis] for pos in region if pos[axis] == i] line.sort() last_j = None for j in line: if not axis: opos = oi, j else: opos = j, oi if opos in region: last_j = None continue if last_j == j - 1: pass else: peri += 1 last_j = j return peri tprice = 0 for i in range(height): for j in range(width): pos = i, j if pos in visited: continue region = get_region(pos, set()) visited |= region area = len(region) sides = get_sides(region) price = area * sides tprice += price char = lines[i][j] print(f"{char}: {area} × {sides} = {price}$") print(tprice)