part02.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import argparse
  2. import functools
  3. from typing import NamedTuple, List, Dict, Set, Tuple
  4. parser = argparse.ArgumentParser()
  5. parser.add_argument("ifile", type=argparse.FileType('r'))
  6. args = parser.parse_args()
  7. heightmap = [[int(x) for x in line.strip()] for line in args.ifile.readlines()]
  8. def printMap(map: List[List]):
  9. for line in map:
  10. print("".join([str(int(el)) for el in line]))
  11. def printColorMap(map: List[List]):
  12. for line in map:
  13. print("".join([el for el in line]))
  14. def descendingMap(seq: List[int]) -> List[bool]:
  15. return [True] + list(map(lambda pair: pair[0] < pair[1], zip(seq[1:], seq)))
  16. right = map(descendingMap, heightmap)
  17. left = map(lambda line: reversed(descendingMap(list(reversed(line)))), heightmap)
  18. horiz = [[all(pair) for pair in line] for line in map(lambda pair: zip(pair[0], pair[1]), zip(right, left))]
  19. # transpose array to check cols
  20. flipped = [[heightmap[j][i] for j in range(len(heightmap))] for i in range(len(heightmap[0]))]
  21. up = map(descendingMap, flipped)
  22. down = map(lambda line: reversed(descendingMap(list(reversed(line)))), flipped)
  23. pre_vert = [[all(pair) for pair in line] for line in map(lambda pair: zip(pair[0], pair[1]), zip(up, down))]
  24. # transpose back
  25. vert = [[pre_vert[j][i] for j in range(len(pre_vert))] for i in range(len(pre_vert[0]))]
  26. composite = [[all(pair) for pair in line] for line in map(lambda pair: zip(pair[0], pair[1]), zip(horiz, vert))]
  27. paired = [[pair[0] + 1 if pair[1] else 0 for pair in line] for line in map(lambda pair: zip(pair[0], pair[1]), zip(heightmap, composite))]
  28. def neighborsForPos(x: int, y: int):
  29. return list(filter(lambda pair: 0 <= pair[0] and pair[0] < len(heightmap[0]) and 0 <= pair[1] and pair[1] < len(heightmap),
  30. [(x - 1, y), (x, y + 1), (x + 1, y), (x, y - 1)]))
  31. # printMap(heightmap)
  32. # print()
  33. # printMap(composite)
  34. # print()
  35. def search(start_x: int, start_y: int, been: set[Tuple[int, int]]) -> int:
  36. been.add((start_x, start_y))
  37. our_val = heightmap[start_y][start_x]
  38. for neighbor in filter(lambda neighbor: neighbor not in been, neighborsForPos(start_x, start_y)):
  39. neighbor_val = heightmap[neighbor[1]][neighbor[0]]
  40. if (neighbor_val != 9) and (neighbor_val > our_val):
  41. search(neighbor[0], neighbor[1], been)
  42. basins: List[Set[Tuple[int, int]]] = []
  43. for y in range(0, len(heightmap)):
  44. for x in range(0, len(heightmap[0])):
  45. if composite[y][x]:
  46. been: Set[Tuple[int, int]] = set()
  47. search(x, y, been)
  48. basins.append(been)
  49. # colors = "ABCDEFGHIJK"
  50. # colormap = [["." for _ in range(0, len(heightmap[0]))] for _ in heightmap]
  51. # for index, basin in enumerate(basins):
  52. # for point in basin:
  53. # colormap[point[1]][point[0]] = colors[index]
  54. # print(basins)
  55. # printColorMap(colormap)
  56. basin_sizes = list(map(len, basins))
  57. basin_sizes.sort()
  58. print(functools.reduce(lambda acc, val: acc * val, basin_sizes[::-1][:3]))