day23: p2 *should* work, but maximum recursion depth ...
This commit is contained in:
parent
52668314e7
commit
8b4e3b9951
157
day23.py
Normal file
157
day23.py
Normal file
@ -0,0 +1,157 @@
|
||||
from tools.aoc import AOCDay
|
||||
from typing import Any
|
||||
|
||||
|
||||
def getLegalMoves(positions):
|
||||
#print(positions)
|
||||
movers = [c for c in positions if positions[c]]
|
||||
|
||||
for start in movers:
|
||||
finalPosition = True
|
||||
if start[1] == 0 or start[0] != positions[start] * 2:
|
||||
finalPosition = False
|
||||
else:
|
||||
if start[1] > 0 and start[0] == positions[start] * 2:
|
||||
for y in range(start[1] + 1, 5):
|
||||
if (start[0], y) in positions and positions[(start[0], y)] != positions[start]:
|
||||
#print("I'm in the right pot, but wrong position:", positions[start], start, positions[(start[0], y)], (start[0], y))
|
||||
finalPosition = False
|
||||
|
||||
if finalPosition:
|
||||
continue
|
||||
|
||||
if start[1] > 0 and positions[(start[0], start[1] - 1)]:
|
||||
continue
|
||||
|
||||
possible_targets = []
|
||||
target_x = positions[start] * 2
|
||||
for y in [4, 3, 2, 1]:
|
||||
target = (target_x, y)
|
||||
if target not in positions:
|
||||
continue
|
||||
|
||||
if positions[target] == positions[start]:
|
||||
continue
|
||||
|
||||
if positions[(target_x, y - 1)]:
|
||||
continue
|
||||
|
||||
possible_targets.append(target)
|
||||
break
|
||||
#possible_targets = [(positions[start] * 2, 2)]
|
||||
#if positions[(positions[start] * 2, 2)] == positions[start]:
|
||||
# possible_targets.extend([(positions[start] * 2, 1)])
|
||||
|
||||
if start[1] != 0:
|
||||
possible_targets.extend([(0, 0), (1, 0), (3, 0), (5, 0), (7, 0), (9, 0), (10, 0)])
|
||||
|
||||
for dest in possible_targets:
|
||||
if start == dest or positions[dest] or start[1] == 2 and positions[(start[0], 1)]:
|
||||
continue
|
||||
|
||||
wayClear = True
|
||||
for x in range(min(start[0], dest[0]) + 1, max(start[0], dest[0])):
|
||||
if positions[(x, 0)]:
|
||||
wayClear = False
|
||||
break
|
||||
if not wayClear:
|
||||
continue
|
||||
|
||||
yield start, dest, start[1] + abs(dest[0] - start[0]) + dest[1]
|
||||
|
||||
|
||||
gMinCost = 1e9
|
||||
DP = {}
|
||||
|
||||
|
||||
def isFinalPosition(position, cost):
|
||||
global gMinCost, DP
|
||||
for x in 2, 4, 6, 8:
|
||||
for y in 1, 2:
|
||||
if position[(x, y)] != x // 2:
|
||||
return False
|
||||
|
||||
if gMinCost > cost:
|
||||
print("Found final position with cost", cost)
|
||||
gMinCost = cost
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def play(position, cost, currentMinCost):
|
||||
if cost > gMinCost:
|
||||
return 1e9
|
||||
if (str(position), cost) in DP:
|
||||
return DP[str(position), cost]
|
||||
|
||||
minCost = currentMinCost
|
||||
for move in getLegalMoves(position):
|
||||
new_pos = position.copy()
|
||||
new_pos[move[1]] = new_pos[move[0]]
|
||||
new_pos[move[0]] = 0
|
||||
this_cost = cost + 10 ** (new_pos[move[1]] - 1) * move[2]
|
||||
if this_cost > gMinCost:
|
||||
continue
|
||||
if not isFinalPosition(new_pos, this_cost):
|
||||
this_cost += play(new_pos, this_cost, minCost)
|
||||
DP[str(new_pos), cost + 10 ** (new_pos[move[1]] - 1) * move[2]] = this_cost
|
||||
if this_cost < minCost:
|
||||
minCost = this_cost
|
||||
|
||||
return minCost
|
||||
|
||||
|
||||
class Day(AOCDay):
|
||||
test_solutions_p1 = [12521]
|
||||
test_solutions_p2 = [44169]
|
||||
|
||||
def getStartingPosition(self, part2=False):
|
||||
positions = {}
|
||||
for x in range(11):
|
||||
positions[(x, 0)] = 0
|
||||
|
||||
y1 = self.getInput()[2].split("#")
|
||||
positions[(2, 1)] = ord(y1[3]) - 64
|
||||
positions[(4, 1)] = ord(y1[4]) - 64
|
||||
positions[(6, 1)] = ord(y1[5]) - 64
|
||||
positions[(8, 1)] = ord(y1[6]) - 64
|
||||
if not part2:
|
||||
y2 = self.getInput()[3].split("#")
|
||||
positions[(2, 2)] = ord(y2[1]) - 64
|
||||
positions[(4, 2)] = ord(y2[2]) - 64
|
||||
positions[(6, 2)] = ord(y2[3]) - 64
|
||||
positions[(8, 2)] = ord(y2[4]) - 64
|
||||
else:
|
||||
my1 = "#D#C#B#A#".split("#")
|
||||
positions[(2, 2)] = ord(my1[1]) - 64
|
||||
positions[(4, 2)] = ord(my1[2]) - 64
|
||||
positions[(6, 2)] = ord(my1[3]) - 64
|
||||
positions[(8, 2)] = ord(my1[4]) - 64
|
||||
my2 = "#D#B#A#C#".split("#")
|
||||
positions[(2, 3)] = ord(my2[1]) - 64
|
||||
positions[(4, 3)] = ord(my2[2]) - 64
|
||||
positions[(6, 3)] = ord(my2[3]) - 64
|
||||
positions[(8, 3)] = ord(my2[4]) - 64
|
||||
y2 = self.getInput()[3].split("#")
|
||||
positions[(2, 4)] = ord(y2[1]) - 64
|
||||
positions[(4, 4)] = ord(y2[2]) - 64
|
||||
positions[(6, 4)] = ord(y2[3]) - 64
|
||||
positions[(8, 4)] = ord(y2[4]) - 64
|
||||
|
||||
return positions
|
||||
|
||||
def part1(self) -> Any:
|
||||
global gMinCost
|
||||
gMinCost = 1e9
|
||||
initPos = self.getStartingPosition()
|
||||
play(initPos, 0, 1e9)
|
||||
return gMinCost
|
||||
|
||||
def part2(self) -> Any:
|
||||
global gMinCost
|
||||
gMinCost = 1e9
|
||||
initPos = self.getStartingPosition(part2=True)
|
||||
print(initPos)
|
||||
print(len(list(getLegalMoves(initPos))), list(getLegalMoves(initPos)))
|
||||
play(initPos, 0, 1e9)
|
||||
return gMinCost
|
||||
5
inputs/input23
Normal file
5
inputs/input23
Normal file
@ -0,0 +1,5 @@
|
||||
#############
|
||||
#...........#
|
||||
###C#D#D#A###
|
||||
#B#A#B#C#
|
||||
#########
|
||||
5
inputs/test_input23_1_0
Normal file
5
inputs/test_input23_1_0
Normal file
@ -0,0 +1,5 @@
|
||||
#############
|
||||
#...........#
|
||||
###B#C#B#D###
|
||||
#A#D#C#A#
|
||||
#########
|
||||
5
inputs/test_input23_2_0
Normal file
5
inputs/test_input23_2_0
Normal file
@ -0,0 +1,5 @@
|
||||
#############
|
||||
#...........#
|
||||
###B#C#B#D###
|
||||
#A#D#C#A#
|
||||
#########
|
||||
Loading…
Reference in New Issue
Block a user