day 18 part 1
parent
d1a2b1eeb1
commit
16637ab722
|
@ -0,0 +1,105 @@
|
|||
from heapq import heappush, heappop
|
||||
|
||||
def search(start, is_goal, neighbors, heuristic=None, worst=None):
|
||||
if heuristic == None:
|
||||
def heuristic(x):
|
||||
return 0
|
||||
if not callable(is_goal):
|
||||
goal = is_goal
|
||||
def is_goal(this):
|
||||
return this == goal
|
||||
if not isinstance(start, list):
|
||||
start = [start]
|
||||
i = 0 # tiebreaker
|
||||
q = []
|
||||
for s in start:
|
||||
i += 1
|
||||
heappush(q, (heuristic(s), i, s, None))
|
||||
done = {}
|
||||
if worst:
|
||||
best_worst = min(worst(s) for s in start)
|
||||
while q:
|
||||
z, _, this, prev = heappop(q)
|
||||
if this in done:
|
||||
continue
|
||||
cost_so_far = z - heuristic(this)
|
||||
#print(this,z, cost_so_far)
|
||||
|
||||
done[this] = (cost_so_far, prev)
|
||||
|
||||
if is_goal(this):
|
||||
print("astar: visited", len(done), "nodes")
|
||||
print("astar: pending", len(q), "nodes")
|
||||
# reconsruct the path
|
||||
n = this
|
||||
path = []
|
||||
while n is not None:
|
||||
path.append(n)
|
||||
_, n = done[n]
|
||||
path.reverse()
|
||||
return cost_so_far, this, path
|
||||
|
||||
for c, n in neighbors(this):
|
||||
c = cost_so_far + c
|
||||
if n not in done or c < done[n][0]:
|
||||
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
|
||||
heappush(q, (c+h, i, n, this))
|
||||
|
||||
return float('inf'), None, []
|
||||
|
||||
def test():
|
||||
data = [
|
||||
"aabqponm",
|
||||
"abcryxxl",
|
||||
"accszzxk",
|
||||
"acctuvwj",
|
||||
"abdefghi",
|
||||
]
|
||||
#data = [
|
||||
# "aabbaaba",
|
||||
# "abcbaaba",
|
||||
# "accabcbb",
|
||||
# "accbbbba",
|
||||
# "abbbabab",
|
||||
#]
|
||||
start = (0,0)
|
||||
goal = (5,2)
|
||||
|
||||
def get(x,y):
|
||||
return ord(data[y][x])
|
||||
|
||||
def neighbors(src):
|
||||
x,y = src
|
||||
here = get(x,y)
|
||||
n = []
|
||||
def push(x,y):
|
||||
if 0 <= y < len(data):
|
||||
if 0 <= x < len(data[y]):
|
||||
if get(x,y) <= here+1:
|
||||
n.append((1, (x,y)))
|
||||
push(x-1, y)
|
||||
push(x+1,y)
|
||||
push(x, y-1)
|
||||
push(x, y+1)
|
||||
return n
|
||||
|
||||
def heuristic(n):
|
||||
return abs(goal[0] - n[0]) + abs(goal[1] - n[1])
|
||||
|
||||
c, _, path = search(start, goal, neighbors, heuristic)
|
||||
print(*data, sep="\n")
|
||||
print(*path, sep="\n")
|
||||
assert c == 31, c
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,25 @@
|
|||
5,4
|
||||
4,2
|
||||
4,5
|
||||
3,0
|
||||
2,1
|
||||
6,3
|
||||
2,4
|
||||
1,5
|
||||
0,6
|
||||
3,3
|
||||
2,6
|
||||
5,1
|
||||
1,2
|
||||
5,5
|
||||
2,5
|
||||
6,5
|
||||
1,4
|
||||
0,4
|
||||
6,4
|
||||
1,1
|
||||
6,1
|
||||
1,0
|
||||
0,5
|
||||
1,6
|
||||
2,0
|
|
@ -0,0 +1,7 @@
|
|||
...#...
|
||||
..#..#.
|
||||
....#..
|
||||
...#..#
|
||||
..#..#.
|
||||
.#..#..
|
||||
#.#....
|
|
@ -0,0 +1,7 @@
|
|||
<em>O</em><em>O</em>.#<em>O</em><em>O</em><em>O</em>
|
||||
.<em>O</em>#<em>O</em><em>O</em>#<em>O</em>
|
||||
.<em>O</em><em>O</em><em>O</em>#<em>O</em><em>O</em>
|
||||
...#<em>O</em><em>O</em>#
|
||||
..#<em>O</em><em>O</em>#.
|
||||
.#.<em>O</em>#..
|
||||
#.#<em>O</em><em>O</em><em>O</em><em>O</em>
|
|
@ -0,0 +1,47 @@
|
|||
from collections import defaultdict
|
||||
import astar
|
||||
|
||||
def parse(file):
|
||||
return [
|
||||
tuple([int(x) for x in line.strip().split(',')])
|
||||
for line in file
|
||||
]
|
||||
|
||||
def solve(file, N=70, T=1024):
|
||||
falling = parse(file)
|
||||
|
||||
start = (0,0,0) # x,y,t
|
||||
|
||||
map = [[0]*N for _ in range(N)]
|
||||
inf = float('inf')
|
||||
map = defaultdict(lambda: inf)
|
||||
for t,p in enumerate(falling):
|
||||
map[p] = t
|
||||
|
||||
def neighbors(n):
|
||||
x,y,t = n
|
||||
#if T < map[x,y]:
|
||||
# can't move out of a blocked space
|
||||
# return []
|
||||
def push(x,y,t):
|
||||
if 0 <= x < N and 0 <= y < N:
|
||||
if T <= map[x,y]:
|
||||
out.append((1,(x,y,t)))
|
||||
out = []
|
||||
push(x+1,y,t+1)
|
||||
push(x,y+1,t+1)
|
||||
push(x-1,y,t+1)
|
||||
push(x,y-1,t+1)
|
||||
return out
|
||||
|
||||
end = N-1, N-1
|
||||
def isgoal(n):
|
||||
x,y,_ = n
|
||||
return (x,y) == end
|
||||
|
||||
sol = astar.search(start, isgoal, neighbors)
|
||||
print(sol)
|
||||
print(len(sol[-1])-1)
|
||||
|
||||
solve(open("sample1.in"), N=7, T=12)
|
||||
solve(open("input"), N=71, T=1024)
|
Loading…
Reference in New Issue