Solve 2018 day 17
This commit is contained in:
parent
ab2e6f4ddb
commit
b88326a7d1
136
2018/d17.py
Normal file
136
2018/d17.py
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
from lib import get_data, str_to_ints, add2
|
||||||
|
|
||||||
|
|
||||||
|
def above(p):
|
||||||
|
return add2(p, (0, -1))
|
||||||
|
|
||||||
|
|
||||||
|
def below(p):
|
||||||
|
return add2(p, (0, 1))
|
||||||
|
|
||||||
|
|
||||||
|
def right(p):
|
||||||
|
return add2(p, (1, 0))
|
||||||
|
|
||||||
|
|
||||||
|
def left(p):
|
||||||
|
return add2(p, (-1, 0))
|
||||||
|
|
||||||
|
|
||||||
|
def print2d(xs, ys=[], zs=[], cs=".#~|"):
|
||||||
|
xs, ys, zs = set(xs), set(ys), set(zs)
|
||||||
|
all = xs | ys | zs
|
||||||
|
x_min, x_max, y_min, y_max = 10**9, 0, 10**9, 0
|
||||||
|
for x, y in all:
|
||||||
|
x_min = min(x_min, x)
|
||||||
|
y_min = min(y_min, y)
|
||||||
|
x_max = max(x_max, x)
|
||||||
|
y_max = max(y_max, y)
|
||||||
|
for y in range(y_min, y_max + 1):
|
||||||
|
row = ""
|
||||||
|
for x in range(x_min, x_max + 1):
|
||||||
|
if (x, y) in xs:
|
||||||
|
row += cs[1]
|
||||||
|
elif (x, y) in ys:
|
||||||
|
row += cs[2]
|
||||||
|
elif (x, y) in zs:
|
||||||
|
row += cs[3]
|
||||||
|
else:
|
||||||
|
row += cs[0]
|
||||||
|
print(row)
|
||||||
|
|
||||||
|
|
||||||
|
def part_1(data):
|
||||||
|
sand = []
|
||||||
|
max_y = 0
|
||||||
|
min_y = 10**9
|
||||||
|
for line in data.splitlines():
|
||||||
|
line = line.strip()
|
||||||
|
a, b, c = str_to_ints(line)
|
||||||
|
if line.startswith("x"):
|
||||||
|
x = a
|
||||||
|
for y in range(b, c + 1):
|
||||||
|
max_y = max(max_y, y)
|
||||||
|
min_y = min(min_y, y)
|
||||||
|
sand.append((x, y))
|
||||||
|
elif line.startswith("y"):
|
||||||
|
y = a
|
||||||
|
max_y = max(max_y, y)
|
||||||
|
min_y = min(min_y, y)
|
||||||
|
for x in range(b, c + 1):
|
||||||
|
sand.append((x, y))
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
|
||||||
|
# TODO: probably should use 2D array for better perf
|
||||||
|
sources = [(500, 0)]
|
||||||
|
water = set()
|
||||||
|
sand = set(sand)
|
||||||
|
water_rest = set()
|
||||||
|
|
||||||
|
while sources:
|
||||||
|
source = sources.pop()
|
||||||
|
current = below(source)
|
||||||
|
while current[1] <= max_y:
|
||||||
|
if current[1] < min_y:
|
||||||
|
current = below(current)
|
||||||
|
elif current in water_rest:
|
||||||
|
break
|
||||||
|
elif below(current) in sand or below(current) in water_rest:
|
||||||
|
water.add(current)
|
||||||
|
c = current
|
||||||
|
to_water_rest = [current]
|
||||||
|
left_sand, right_sand = False, False
|
||||||
|
while True:
|
||||||
|
c = right(c)
|
||||||
|
if c in sand:
|
||||||
|
right_sand = True
|
||||||
|
break
|
||||||
|
elif below(c) in sand or below(c) in water_rest:
|
||||||
|
water.add(c)
|
||||||
|
to_water_rest.append(c)
|
||||||
|
else:
|
||||||
|
# it's empty underneath
|
||||||
|
water.add(c)
|
||||||
|
sources.append(c)
|
||||||
|
break
|
||||||
|
|
||||||
|
c = current
|
||||||
|
while True:
|
||||||
|
c = left(c)
|
||||||
|
if c in sand:
|
||||||
|
left_sand = True
|
||||||
|
break
|
||||||
|
elif below(c) in sand or below(c) in water_rest:
|
||||||
|
water.add(c)
|
||||||
|
to_water_rest.append(c)
|
||||||
|
else:
|
||||||
|
# it's empty underneath
|
||||||
|
water.add(c)
|
||||||
|
sources.append(c)
|
||||||
|
break
|
||||||
|
|
||||||
|
if left_sand and right_sand:
|
||||||
|
sources.append(above(above(current)))
|
||||||
|
for w in to_water_rest:
|
||||||
|
water_rest.add(w)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
water.add(current)
|
||||||
|
current = below(current)
|
||||||
|
|
||||||
|
# print2d(sand, water_rest, water)
|
||||||
|
# print(sources)
|
||||||
|
# input()
|
||||||
|
current_water = len(water_rest | water)
|
||||||
|
print(current_water)
|
||||||
|
print(len(water_rest))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
data = get_data(__file__)
|
||||||
|
part_1(data)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user