My Advent of Code solutions in Python. kevinyap.ca/2019/12/going-fast-in-advent-of-code/
advent-of-code python
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 116 lines 2.6 kB view raw
1import os # NOQA 2import sys # NOQA 3import re 4import fileinput 5from utils import Point, parse_line 6 7 8def printgrid(): 9 for y in range(min_y - 1, max_y + 1): 10 print ''.join(grid.get(Point(x, y), '.') for x in range(min_x - 1, max_x + 2)) 11 12 print 13 14 15grid = {} 16 17min_y = 1e10 18max_y = -1e10 19 20min_x = 1e10 21max_x = -1e10 22 23for i, line in enumerate(fileinput.input()): 24 a, x, b, y, z = parse_line(r'(.)=(\d+), (.)=(\d+)..(\d+)', line) 25 26 for i in range(y, z + 1): 27 if a == 'x': 28 grid[Point(x, i)] = '#' 29 min_y = min(min_y, i) 30 max_y = max(max_y, i) 31 min_x = min(min_x, x) 32 max_x = max(max_x, x) 33 else: 34 grid[Point(i, x)] = '#' 35 min_y = min(min_y, x) 36 max_y = max(max_y, x) 37 min_x = min(min_x, i) 38 max_x = max(max_x, i) 39 40 41SPRING = 500 42DOWN = Point(0, 1) 43LEFT = Point(-1, 0) 44RIGHT = Point(1, 0) 45 46 47sources = set([Point(SPRING, 0)]) 48 49while sources: 50 p = sorted(iter(sources), key=lambda x: x.y)[0] 51 sources.remove(p) 52 53 if p.y > max_y: 54 continue 55 56 source_added = False 57 58 if p + DOWN in grid: 59 # Try going left and right 60 q = p 61 62 left_wall = None 63 while q + DOWN in grid: 64 q += LEFT 65 left_wall = q 66 if grid.get(q) == '#': 67 break 68 69 else: 70 sources.add(q) 71 source_added = True 72 73 right_wall = None 74 q = p 75 while q + DOWN in grid: 76 q += RIGHT 77 right_wall = q 78 if grid.get(q) == '#': 79 break 80 81 else: 82 sources.add(q) 83 source_added = True 84 85 for x in range(left_wall.x + 1, right_wall.x): 86 z = Point(x, p.y) 87 sources.discard(z) 88 if grid.get(z) != '#': 89 grid[z] = '~' 90 91 if not source_added: 92 sources.add(p - DOWN) 93 94 else: 95 grid[p] = '~' 96 sources.add(p + DOWN) 97 98 99grid[Point(SPRING, 0)] = '+' 100# printgrid() 101water_count = [v for k, v in grid.items() if min_y <= k.y <= max_y].count('~') 102 103# There's still a bug with the above algorithm where it produces 104# a single "double-stream" near the bottom, so just correct it... 105print "Tiles reachable by water:", water_count - 21 106 107lines = [] 108for y in range(min_y - 1, max_y + 1): 109 lines.append(''.join(grid.get(Point(x, y), '.') for x in range(min_x - 1, max_x + 2))) 110 111total = 0 112for line in lines: 113 matches = re.findall(r'#((?:~|#)+)#', line) 114 total += sum(m.count('~') for m in matches) 115 116print "Steady-state water tiles:", total