2018-12-17 17:16:03 +10:30
with open ( ' day17-input ' , ' r ' ) as file :
data = [ l . strip ( ' \n ' ) for l in file ]
import numpy as np
import re
# numbers = [[int(s) for s in re.findall(r'-?\d+', d)] for d in data]
Xmin = [ int ( re . findall ( r ' x=( \ d+) ' , d ) [ 0 ] ) for d in data ]
Xmax = [ int ( re . findall ( r ' x=(?: \ d+ \ . \ .)?( \ d+) ' , d ) [ 0 ] ) for d in data ]
Ymin = [ int ( re . findall ( r ' y=( \ d+) ' , d ) [ 0 ] ) for d in data ]
Ymax = [ int ( re . findall ( r ' y=(?: \ d+ \ . \ .)?( \ d+) ' , d ) [ 0 ] ) for d in data ]
# arr = np.array(numbers, dtype=np.int64)
#
# # x, y_start, y_end
#
y_min = min ( Ymin )
y_max = max ( Ymax )
2018-12-17 20:18:23 +10:30
x_min = min ( Xmin ) - 1
x_max = 700 - x_min
2018-12-17 17:16:03 +10:30
2018-12-17 20:18:23 +10:30
init_grid = np . zeros ( ( x_max , y_max + 1 ) , dtype = np . int64 ) # 0 = Sand, 1 = Clay, 2 = water, -1 = running water
spring = [ 500 - x_min , 0 ]
2018-12-17 17:16:03 +10:30
for xmin , xmax , ymin , ymax in zip ( Xmin , Xmax , Ymin , Ymax ) :
2018-12-17 20:18:23 +10:30
init_grid [ xmin - x_min : xmax + 1 - x_min , ymin : ymax + 1 ] = 1
2018-12-17 17:16:03 +10:30
grid = init_grid . copy ( )
2018-12-17 20:18:23 +10:30
def drop_water ( source = spring , skip_cliffs = set ( ) ) :
# TODO: The exit condition on this is borked and it will probably run forever. Killing it after like a minute and then running the things at the end gives the right answers.
# I'll probably revisit this properly later
2018-12-17 17:16:03 +10:30
x , y = source
2018-12-17 20:18:23 +10:30
# print('Dropping water from', source)
surface = ( grid [ x , y : ] > 0 ) . argmax ( )
2018-12-17 17:16:03 +10:30
if surface == 0 :
2018-12-17 20:18:23 +10:30
if ( grid [ x , y - 1 : ] > 0 ) . argmax ( ) == 0 :
grid [ x , y : ] = - 1
2018-12-17 17:16:03 +10:30
return False
# raise ValueError('Out of bounds')
2018-12-17 20:18:23 +10:30
surface_y = surface + y
grid [ x , y : surface_y ] = - 1
2018-12-17 17:16:03 +10:30
# Find walls left and right
2018-12-17 20:18:23 +10:30
wall_left = ( grid [ x : 0 : - 1 , surface_y - 1 ] > 0 ) . argmax ( )
wall_right = ( grid [ x : , surface_y - 1 ] > 0 ) . argmax ( )
2018-12-17 17:16:03 +10:30
if wall_left :
left_x = x - wall_left + 1
2018-12-17 20:18:23 +10:30
cliff = ( grid [ x : left_x - 1 : - 1 , surface_y ] < = 0 ) . argmax ( )
2018-12-17 17:16:03 +10:30
if cliff :
wall_left = False
if wall_right :
right_x = x + wall_right #- 1
2018-12-17 20:18:23 +10:30
cliff = ( grid [ x : right_x , surface_y ] < = 0 ) . argmax ( )
2018-12-17 17:16:03 +10:30
if cliff :
wall_right = False
if wall_right and wall_left :
# Fill level of basin
2018-12-17 20:18:23 +10:30
grid [ left_x : right_x , surface_y - 1 ] = 2
2018-12-17 17:16:03 +10:30
return True
2018-12-17 20:18:23 +10:30
cliffs = set ( )
2018-12-17 17:16:03 +10:30
if not wall_left :
2018-12-17 20:18:23 +10:30
cliff = int ( ( grid [ x : 0 : - 1 , surface_y ] < = 0 ) . argmax ( ) )
grid [ x - cliff : x , surface_y - 1 ] = - 1
if wall_right :
grid [ x : right_x , surface_y - 1 ] = - 1
if cliff and ( cliff not in skip_cliffs ) :
cliffs . add ( ( x - cliff , surface_y ) )
2018-12-17 17:16:03 +10:30
if not wall_right :
2018-12-17 20:18:23 +10:30
cliff = int ( ( grid [ x : , surface_y ] < = 0 ) . argmax ( ) )
grid [ x : x + cliff + 1 , surface_y - 1 ] = - 1
if wall_left :
grid [ left_x : x , surface_y - 1 ] = - 1
if cliff and ( cliff not in skip_cliffs ) :
cliffs . add ( ( x + cliff , surface_y ) )
2018-12-17 17:16:03 +10:30
2018-12-17 20:18:23 +10:30
succeeded = False
while sum ( [ drop_water ( c ) for c in cliffs ] ) :
succeeded = True
return succeeded
2018-12-17 17:16:03 +10:30
def visualize ( ) :
vis_rows = [ ]
2018-12-17 20:18:23 +10:30
for row in range ( y_max + 1 ) :
vis_rows . append ( ' ' . join ( [ ( ' . ' , ' # ' , ' ~ ' , ' | ' ) [ grid [ col , row ] ] for col in range ( x_max ) ] ) )
2018-12-17 17:16:03 +10:30
with open ( ' day17-vis ' , ' w ' ) as file :
file . write ( ' \n ' . join ( vis_rows ) )
2018-12-17 20:18:23 +10:30
import sys
sys . setrecursionlimit ( 10000 )
2018-12-17 17:16:03 +10:30
2018-12-17 20:18:23 +10:30
while drop_water ( ) :
pass
2018-12-17 17:16:03 +10:30
2018-12-17 20:18:23 +10:30
print ( ( grid == 2 ) . sum ( ) + ( grid == - 1 ) . sum ( ) - y_min ) # Part 1
print ( ( grid == 2 ) . sum ( ) ) # Part 2
visualize ( )