Add solution for day 23
This commit is contained in:
1 parent
805d09a907
commit
26c5e404c4
7 files changed
+145
No files matched your search
Executable
+109
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
from functools import cache
|
||||
|
||||
@cache
|
||||
def path(f1,f2):
|
||||
path = []
|
||||
y, x = f1
|
||||
while y != 0:
|
||||
y -= 1
|
||||
path.append((y,x))
|
||||
while x != f2[1]:
|
||||
x += 1 if f2[1] > x else -1
|
||||
path.append((y,x))
|
||||
while y != f2[0]:
|
||||
y += 1
|
||||
path.append((y,x))
|
||||
assert path[-1] == f2
|
||||
return path
|
||||
|
||||
def pathvalid(path,board):
|
||||
for p in path:
|
||||
if p in board: return False
|
||||
return True
|
||||
|
||||
def cost(a,w):
|
||||
if a == 'A': return len(w) * 1
|
||||
if a == 'B': return len(w) * 10
|
||||
if a == 'C': return len(w) * 100
|
||||
if a == 'D': return len(w) * 1000
|
||||
|
||||
def endstate(board):
|
||||
for f,a in board.items():
|
||||
if f[1] != target[a]: return False
|
||||
return True
|
||||
|
||||
def target_position(f,b,lowest):
|
||||
a = b[f]
|
||||
if f[1] != target[a]: return False
|
||||
for y in range(f[0],lowest+1):
|
||||
if (y,target[a]) not in b: return False
|
||||
if b[(y,target[a])] != a: return False
|
||||
return True
|
||||
|
||||
def totarget(board,lowest):
|
||||
change = False
|
||||
costs = 0
|
||||
nb = {k: v for k,v in board.items()}
|
||||
for f,a in board.items():
|
||||
if target_position(f,nb,lowest): continue
|
||||
t = (lowest,target[a])
|
||||
while t in nb and nb[t] == a:
|
||||
t = (t[0]-1,target[a])
|
||||
if t == (0,target[a]): continue
|
||||
p = path(f,t)
|
||||
if pathvalid(p,nb):
|
||||
change = True
|
||||
nb.pop(f)
|
||||
nb[t] = a
|
||||
costs += cost(a,p)
|
||||
return nb,costs,change
|
||||
|
||||
def dfs(board,lowest,costs=0,curmin=sys.maxsize):
|
||||
ch = True
|
||||
nb = {k: v for k,v in board.items()}
|
||||
while ch:
|
||||
nb,co,ch = totarget(nb,lowest)
|
||||
costs += co
|
||||
if endstate(nb):
|
||||
return costs
|
||||
if costs > curmin: return None
|
||||
board = {k: v for k,v in nb.items()}
|
||||
for f,a in board.items():
|
||||
if f[0] != 0 and not(target_position(f,board,lowest)):
|
||||
for f2 in hallway:
|
||||
p = path(f,f2)
|
||||
if pathvalid(p, board):
|
||||
cb = {k: v for k,v in board.items()}
|
||||
cb.pop(f)
|
||||
cb[f2] = a
|
||||
nc = dfs(cb,lowest,costs+cost(a,p),curmin)
|
||||
if nc is not None and nc < curmin: curmin = nc
|
||||
if curmin < sys.maxsize: return curmin
|
||||
|
||||
if __name__ == '__main__':
|
||||
# challenge 1
|
||||
lines = open(sys.argv[1]).readlines()
|
||||
start = {}
|
||||
for y,l in enumerate(lines[1:]):
|
||||
for x,f in enumerate(l[1:]):
|
||||
if f in 'ABCD': start[(y,x)] = f
|
||||
|
||||
hallway = [(0,0), (0,1), (0,3), (0,5), (0,7), (0,9), (0,10)]
|
||||
target = {'A': 2, 'B': 4, 'C': 6, 'D': 8}
|
||||
|
||||
res1 = str(dfs(start,2))
|
||||
print("challenge 1:" + "\n" + res1 + "\n")
|
||||
|
||||
# challenge 2
|
||||
lines = open(sys.argv[2]).readlines()
|
||||
start = {}
|
||||
for y,l in enumerate(lines[1:]):
|
||||
for x,f in enumerate(l[1:]):
|
||||
if f in 'ABCD': start[(y,x)] = f
|
||||
|
||||
res2 = str(dfs(start,4))
|
||||
print("challenge 2:" + "\n" + res2 + "\n")
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#############
|
||||
#...........#
|
||||
###A#C#B#A###
|
||||
#D#D#B#C#
|
||||
#########
|
||||
@@ -0,0 +1,7 @@
|
||||
#############
|
||||
#...........#
|
||||
###A#C#B#A###
|
||||
#D#C#B#A#
|
||||
#D#B#A#C#
|
||||
#D#D#B#C#
|
||||
#########
|
||||
@@ -0,0 +1,5 @@
|
||||
#############
|
||||
#...........#
|
||||
###B#C#B#D###
|
||||
#A#D#C#A#
|
||||
#########
|
||||
@@ -0,0 +1,7 @@
|
||||
#############
|
||||
#...........#
|
||||
###B#C#B#D###
|
||||
#D#C#B#A#
|
||||
#D#B#A#C#
|
||||
#A#D#C#A#
|
||||
#########
|
||||
@@ -0,0 +1,5 @@
|
||||
#############
|
||||
#.....D.D.A.#
|
||||
###.#B#C#.###
|
||||
#A#B#C#.#
|
||||
#########
|
||||
@@ -0,0 +1,7 @@
|
||||
#############
|
||||
#AA.D......D#
|
||||
###B#.#C#.###
|
||||
#D#B#C#.#
|
||||
#D#B#C#.#
|
||||
#A#B#C#A#
|
||||
#########
|
||||
Reference in new issue
Block a user