-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday23.krk
147 lines (123 loc) · 4.02 KB
/
day23.krk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env kuroko
'''
Day 23
'''
let costs = {
'A': 1,
'B': 10,
'C': 100,
'D': 1000
}
let homes = {
'A': 2,
'B': 4,
'C': 6,
'D': 8
}
class Pod:
def __init__(self,x,y,ch):
self.x = x
self.y = y
self.ch = ch
self.home = homes[ch]
def move_to(self,world,dx,dy):
if dy > 0 and self.y != 0: return False
if dy == 0 and self.y == 0: return False
if self.y == 2 and world[1][self.x] != 'x':
return False
if dy == 0 and world[dy][dx] != '.':
return False
if dx < self.x:
for i in range(dx,self.x):
if world[0][i] != '.' and world[0][i] != 'x':
return False
if dx > self.x:
for i in range(self.x+1,dx+1):
if world[0][i] != '.' and world[0][i] != 'x':
return False
world[self.y][self.x] = ('x' if self.y > 0 else '.')
self.y = dy
self.x = dx
world[self.y][self.x] = self.ch
return True
def try_for_home(self,world):
if self.y == 0 and world[2][self.home] == 'x':
return self.move_to(world,self.home,2)
if self.y == 0 and world[2][self.home] == self.ch and world[1][self.home] == 'x':
return self.move_to(world,self.home,1)
return False
@staticmethod
def copy(other):
return Pod(other.x,other.y,other.ch)
def calculateCost(moves,pods):
def initialSpot(n):
if n < 4: return n * 2 + 2
return (n - 4) * 2 + 2
def calc(n,d):
let init_x = initialSpot(n)
let init_y = 1 if n < 4 else 2
return (abs(init_x - d) + init_y + abs(pods[n].x - d) + pods[n].y) * costs[pods[n].ch]
return sum(calc(n,d) for n,d in moves)
let try_pods
let nums = [0,1,2,3,4,5,6,7]
let currentWinner = False
def simulate(moved, moves, world, pods, next, currentScore):
let mover, dest = next
# Create a fresh state to simulate here
let nworld = [[x for x in y] for y in world]
let npods = [Pod.copy(pod) for pod in pods]
# Can we make this move?
if not npods[mover].move_to(nworld, dest, 0):
return False
let scoreCost = calculateCost([next],npods)
if currentWinner is not False and currentScore + scoreCost >= currentWinner:
return False
# Move all the things that can go home this turn.
let _moved = True
while _moved:
_moved = False
for p in npods:
if p.try_for_home(nworld):
_moved = True
# Is everything home already?
if all((pod.x == pod.home and pod.y > 0) for pod in npods):
let res = calculateCost(moves,npods)
#print('\n'.join(''.join(x) for x in nworld))
#print(moves,res)
return res
currentScore += scoreCost
# Otherwise, we need to simulate another move
return try_pods([x for x in nums if x not in moved], npods, nworld, moved, moves, currentScore)
import gc
def _try_pods(movers,pods,world,moved=set(),moves=[],currentScore=0):
let myWinner = False
for mover in movers:
moved.add(mover)
for move in [0,1,3,5,7,9,10]:
moves.append((mover,move))
let maybe = simulate(moved,moves,world,pods,(mover,move),currentScore)
if maybe is not False:
if myWinner is False or maybe < myWinner:
myWinner = maybe
moves.pop()
moved.remove(mover)
if myWinner is not False and (currentWinner is False or myWinner < currentWinner):
currentWinner = myWinner
if len(moved) == 2:
print(currentWinner,moves)
#gc.collect()
return myWinner
try_pods = _try_pods
def try_one():
let world = [
list('..x.x.x.x..'),
list('##D#A#A#D##'),
list('##C#C#B#B##'),
]
let pods = []
for y in range(len(world)):
for x in range(len(world[y])):
if world[y][x] not in '.x#':
pods.append(Pod(x,y,world[y][x]))
print(try_pods([0,1,2,3],pods,world))
try_one()