source = (500,0) data = [] for line in open("input"): path = [] for point in line.replace("->", " ").split(): x, y = map(int, point.split(",")) path.append((x,y)) data.append(path) grid = {} X0 = 500 X1 = 500 + 1 Y0 = 0 Y1 = 1 def put(x,y,c): global X0, X1, Y0, Y1 if x < X0: X0 = x if x >= X1: X1 = x + 1 if y < Y0: Y0 = y if y >= Y1: Y1 = y + 1 grid[(x,y)] = c def get(x,y): return grid.get((x,y), '.') def minmax(a,b): if a < b: return a, b return b, a def draw(path): for (x0,y0), (x1,y1) in zip(path, path[1:]): #print((x0,y0), (x1,y1)) x0, x1 = minmax(x0, x1) y0, y1 = minmax(y0, y1) for y in range(y0, y1+1): put(x0,y, '#') for x in range(x0, x1+1): put(x,y0, '#') for path in data: #print(path) draw(path) def show(): for y in range(Y0, Y1): print("".join(get(x,y) for x in range(X0, X1))) show() def drip(p, floor=None, lastpath=[]): x,y=p if p in lastpath: x,y = lastpath.pop() else: lastpath[:] = [] blocked = False while not blocked: lastpath.append((x,y)) if y+1 == floor: break if y >= Y1: return 'bye' # falls forever # try straight down, then left, then right for x1 in x, x-1, x+1: if get(x1,y+1) == '.': x,y = x1,y+1 break # continue else: blocked = True # blocked! lastpath.pop() put(x,y,'o') #print(x,y) return 'done' n = 0 while True: if drip(source) == 'bye': break n+= 1 print(n) floor = Y1 + 1 Y1 = floor+1 show() # keep going while source not in grid: if drip(source, floor=floor) == 'bye': print("whoops") # shouldn't happen break n += 1 # 28594 #show() print(n)