usesbiggerwords

AoC 2021 Day 9

Dec 9th, 2021
266
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.28 KB | None | 0 0
  1. import os
  2. from collections import defaultdict
  3.  
  4.  
  5. def read_and_init(fn):
  6.     with open(fn, 'r') as f:
  7.         lines = f.read().splitlines()
  8.     height_map = defaultdict(int)
  9.     coord = 0j
  10.     for line in lines:
  11.         for c in line:
  12.             height_map[coord] = int(c)
  13.             coord += 1
  14.         coord = 0+coord.imag*1j
  15.         coord += 1j
  16.     return height_map
  17.  
  18.  
  19. def product(vals):
  20.     result = 1
  21.     for v in vals:
  22.         result *= v
  23.     return result
  24.  
  25.  
  26. def in_bounds(loc: complex, lower: complex, upper: complex) -> bool:
  27.     return (lower.real <= loc.real < upper.real) and (lower.imag <= loc.imag < upper.imag)
  28.  
  29.  
  30. def check_local_minima(hmap: defaultdict, loc: complex) -> bool:
  31.     dirs = (-1j, -1, 1, 1j)
  32.     upper = int(max(key.real for key in hmap) + 1)+1j*int(max(key.imag for key in hmap) + 1)
  33.     return all(hmap[loc + d] > hmap[loc] for d in dirs if in_bounds(loc + d, 0j, upper))
  34.  
  35.  
  36. def find_basins(hmap):
  37.     upper = int(max(key.real for key in hmap) + 1) + 1j * int(max(key.imag for key in hmap) + 1)
  38.     minima = get_minima(hmap)
  39.     basins = {}
  40.     dirs = (-1j, -1, 1, 1j)
  41.     for m in minima:
  42.         basins[m] = set()
  43.         queue = [m]
  44.         while queue:
  45.             current = queue.pop(0)
  46.             for neighbor in [current + d for d in dirs if in_bounds(current + d, 0j, upper)]:
  47.                 if hmap[neighbor] == 9:
  48.                     continue
  49.                 if neighbor not in basins[m]:
  50.                     basins[m].add(neighbor)
  51.                     queue.append(neighbor)
  52.     return basins
  53.  
  54.  
  55. def get_minima(hmap):
  56.     upper = int(max(key.real for key in hmap) + 1) + 1j * int(max(key.imag for key in hmap) + 1)
  57.     minima = []
  58.     for y in range(int(upper.imag)):
  59.         for x in range(int(upper.real)):
  60.             if check_local_minima(hmap, x + 1j * y):
  61.                 minima.append(x + 1j * y)
  62.     return minima
  63.  
  64.  
  65. def part1(hmap):
  66.     minima = get_minima(hmap)
  67.     return sum(hmap[m] for m in minima)
  68.  
  69.  
  70. def part2(hmap):
  71.     basins = find_basins(hmap)
  72.     basin_sizes = [len(basins[m]) for m in basins]
  73.     basin_sizes.sort(reverse=True)
  74.     return product(basin_sizes[:3])
  75.  
  76.  
  77. h = read_and_init(os.path.dirname(__file__) + '\\in.txt')
  78. res = part1(h)
  79. print('Part 1:', res)
  80. res = part2(h)
  81. print('Part 2:', res)
Advertisement
Add Comment
Please, Sign In to add comment