Compare commits
7 Commits
5a7c8ef732
...
88040394db
Author | SHA1 | Date | |
---|---|---|---|
88040394db | |||
772dda0bbc | |||
4b5b25e56b | |||
71958605b6 | |||
910da239c0 | |||
e9ada04aa9 | |||
e1fb37d229 |
@ -152,6 +152,10 @@ def solve():
|
|||||||
m -= 1
|
m -= 1
|
||||||
return c
|
return c
|
||||||
|
|
||||||
|
def worst2(node):
|
||||||
|
_, _, min1, min2, closed = node
|
||||||
|
return min(min1,min2) * pressure(closed)
|
||||||
|
|
||||||
def is_goal2(node):
|
def is_goal2(node):
|
||||||
_, _, min1, min2, closed = node
|
_, _, min1, min2, closed = node
|
||||||
return min1 == 0 and min2 == 0 or closed == all_open
|
return min1 == 0 and min2 == 0 or closed == all_open
|
||||||
@ -209,7 +213,7 @@ def solve():
|
|||||||
minutes = 26
|
minutes = 26
|
||||||
start2 = (AA, AA, minutes, minutes, all_closed)
|
start2 = (AA, AA, minutes, minutes, all_closed)
|
||||||
info.clear()
|
info.clear()
|
||||||
c, _, path = astar.search(start2, is_goal2, neighbors2, heuristic2)
|
c, _, path = astar.search(start2, is_goal2, neighbors2, heuristic2, worst=worst2)
|
||||||
print(c)
|
print(c)
|
||||||
print(max_pressure*minutes - c)
|
print(max_pressure*minutes - c)
|
||||||
|
|
||||||
|
2866
day18/input
Normal file
2866
day18/input
Normal file
File diff suppressed because it is too large
Load Diff
1
day18/input.ivy
Normal file
1
day18/input.ivy
Normal file
File diff suppressed because one or more lines are too long
13
day18/sample1.in
Normal file
13
day18/sample1.in
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
2,2,2
|
||||||
|
1,2,2
|
||||||
|
3,2,2
|
||||||
|
2,1,2
|
||||||
|
2,3,2
|
||||||
|
2,2,1
|
||||||
|
2,2,3
|
||||||
|
2,2,4
|
||||||
|
2,2,6
|
||||||
|
1,2,5
|
||||||
|
3,2,5
|
||||||
|
2,1,5
|
||||||
|
2,3,5
|
52
day18/sol.ivy
Normal file
52
day18/sol.ivy
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
) get "input.ivy"
|
||||||
|
|
||||||
|
sample = 13 3 rho 2 2 2 1 2 2 3 2 2 2 1 2 2 3 2 2 2 1 2 2 3 2 2 4 2 2 6 1 2 5 3 2 5 2 1 5 2 3 5
|
||||||
|
#input = sample
|
||||||
|
|
||||||
|
) origin 0
|
||||||
|
|
||||||
|
op makeGrid coords =
|
||||||
|
lo = min/ transp coords
|
||||||
|
hi = max/ transp coords
|
||||||
|
coords = 1 1 1 + coords - lo
|
||||||
|
dim = 2 + (1 + hi - lo)
|
||||||
|
g = ,dim rho 0
|
||||||
|
g[dim decode transp coords] = 1
|
||||||
|
dim rho g
|
||||||
|
|
||||||
|
op makeBorder dim =
|
||||||
|
g = (dim-2) rho 0
|
||||||
|
g = 1,(2 0 1 transp g),1
|
||||||
|
g = 1,(2 0 1 transp g),1
|
||||||
|
g = 1,(2 0 1 transp g),1
|
||||||
|
g
|
||||||
|
|
||||||
|
op n twist a = 1 0 2 transp n flip (1 0 2 transp a)
|
||||||
|
|
||||||
|
op grow a = (1 rot a) or (-1 rot a) or (1 flip a) or (-1 flip a) or (1 twist a) or (-1 twist a)
|
||||||
|
op sides a = (1 rot a) + (-1 rot a) + (1 flip a) + (-1 flip a) + (1 twist a) + (-1 twist a)
|
||||||
|
|
||||||
|
lava = makeGrid input
|
||||||
|
|
||||||
|
"npoints = "; +/ ,lava
|
||||||
|
#lava
|
||||||
|
|
||||||
|
#border = makeBorder rho lava
|
||||||
|
#or/, lava and border # should == 0
|
||||||
|
|
||||||
|
op a flood walls =
|
||||||
|
x = grow a
|
||||||
|
b = (a or x) and not walls
|
||||||
|
and/, a == b: a
|
||||||
|
b flood walls
|
||||||
|
|
||||||
|
op solve2 lava =
|
||||||
|
water = (makeBorder rho lava) flood lava
|
||||||
|
+/, lava * sides water
|
||||||
|
|
||||||
|
op solve1 lava =
|
||||||
|
air = not lava
|
||||||
|
+/, lava * sides air
|
||||||
|
|
||||||
|
"part 1 ="; solve1 lava
|
||||||
|
"part 2 ="; solve2 lava
|
62
day18/sol.py
Normal file
62
day18/sol.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import numpy
|
||||||
|
|
||||||
|
N = 23
|
||||||
|
|
||||||
|
def solve():
|
||||||
|
lava = numpy.zeros((N,N,N), dtype=numpy.int32)
|
||||||
|
for line in open("input"):
|
||||||
|
x,y,z = map(int, line.strip().split(","))
|
||||||
|
lava[x,y,z] = 1
|
||||||
|
|
||||||
|
lava = numpy.pad(lava, (1,1), constant_values=0)
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
area = count_touching(lava, lava^1)
|
||||||
|
print(area)
|
||||||
|
|
||||||
|
# part 2
|
||||||
|
border = numpy.zeros((N,N,N), dtype=numpy.int32)
|
||||||
|
border = numpy.pad(border, (1,1), constant_values=1)
|
||||||
|
|
||||||
|
water = flood(lava, border)
|
||||||
|
#print(water)
|
||||||
|
|
||||||
|
area = count_touching(lava, water)
|
||||||
|
print(area)
|
||||||
|
|
||||||
|
|
||||||
|
def count_touching(A, B):
|
||||||
|
"""counts the number of places a cell in A touches a cell in B
|
||||||
|
(assumes a 1-cell padding around the edge which is not counted)"""
|
||||||
|
n = 0
|
||||||
|
for x in range(1,N+1):
|
||||||
|
for y in range(1,N+1):
|
||||||
|
for z in range(1,N+1):
|
||||||
|
if A[x,y,z]:
|
||||||
|
n += B[x-1,y,z]
|
||||||
|
n += B[x+1,y,z]
|
||||||
|
n += B[x,y-1,z]
|
||||||
|
n += B[x,y+1,z]
|
||||||
|
n += B[x,y,z-1]
|
||||||
|
n += B[x,y,z+1]
|
||||||
|
return n
|
||||||
|
|
||||||
|
def flood(lava, border):
|
||||||
|
def roll(a, axis, amount):
|
||||||
|
return numpy.roll(a, amount, axis=axis)
|
||||||
|
|
||||||
|
a = border
|
||||||
|
while True:
|
||||||
|
x = roll(a, 0, -1)
|
||||||
|
x |= roll(a, 0, +1)
|
||||||
|
x |= roll(a, 1, -1)
|
||||||
|
x |= roll(a, 1, +1)
|
||||||
|
x |= roll(a, 2, -1)
|
||||||
|
x |= roll(a, 2, +1)
|
||||||
|
x &= ~lava
|
||||||
|
b = a | x
|
||||||
|
if (a == b).all():
|
||||||
|
return a
|
||||||
|
a = b
|
||||||
|
|
||||||
|
solve()
|
22
lib/astar.py
22
lib/astar.py
@ -1,6 +1,6 @@
|
|||||||
from heapq import heappush, heappop
|
from heapq import heappush, heappop
|
||||||
|
|
||||||
def search(start, is_goal, neighbors, heuristic=None):
|
def search(start, is_goal, neighbors, heuristic=None, worst=None):
|
||||||
if heuristic == None:
|
if heuristic == None:
|
||||||
def heuristic(x):
|
def heuristic(x):
|
||||||
return 0
|
return 0
|
||||||
@ -16,6 +16,8 @@ def search(start, is_goal, neighbors, heuristic=None):
|
|||||||
i += 1
|
i += 1
|
||||||
heappush(q, (heuristic(s), i, s, None))
|
heappush(q, (heuristic(s), i, s, None))
|
||||||
done = {}
|
done = {}
|
||||||
|
if worst:
|
||||||
|
best_worst = min(worst(s) for s in start)
|
||||||
while q:
|
while q:
|
||||||
z, _, this, prev = heappop(q)
|
z, _, this, prev = heappop(q)
|
||||||
if this in done:
|
if this in done:
|
||||||
@ -27,6 +29,7 @@ def search(start, is_goal, neighbors, heuristic=None):
|
|||||||
|
|
||||||
if is_goal(this):
|
if is_goal(this):
|
||||||
print("astar: visited", len(done), "nodes")
|
print("astar: visited", len(done), "nodes")
|
||||||
|
print("astar: pending", len(q), "nodes")
|
||||||
# reconsruct the path
|
# reconsruct the path
|
||||||
n = this
|
n = this
|
||||||
path = []
|
path = []
|
||||||
@ -37,11 +40,20 @@ def search(start, is_goal, neighbors, heuristic=None):
|
|||||||
return cost_so_far, this, path
|
return cost_so_far, this, path
|
||||||
|
|
||||||
for c, n in neighbors(this):
|
for c, n in neighbors(this):
|
||||||
if n not in done:
|
c = cost_so_far + c
|
||||||
# calculate the "reduced cost"
|
if n not in done or c < done[n][0]:
|
||||||
c = cost_so_far + c + heuristic(n)
|
h = heuristic(n)
|
||||||
|
if worst:
|
||||||
|
if c+h > best_worst:
|
||||||
|
# if the best possible cost for this node
|
||||||
|
# is worse than the lowest worst-case cost we've seen
|
||||||
|
# then don't even bother exploring it
|
||||||
|
continue
|
||||||
|
w = worst(n)
|
||||||
|
if c+w < best_worst:
|
||||||
|
best_worst = c+w
|
||||||
i += 1
|
i += 1
|
||||||
heappush(q, (c, i, n, this))
|
heappush(q, (c+h, i, n, this))
|
||||||
|
|
||||||
return float('inf'), None, []
|
return float('inf'), None, []
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user