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