From 8b4e3b99511c1f1cd37e2181a8325571639393ba Mon Sep 17 00:00:00 2001 From: Stefan Harmuth Date: Thu, 23 Dec 2021 10:09:46 +0100 Subject: [PATCH] day23: p2 *should* work, but maximum recursion depth ... --- day23.py | 157 ++++++++++++++++++++++++++++++++++++++++ inputs/input23 | 5 ++ inputs/test_input23_1_0 | 5 ++ inputs/test_input23_2_0 | 5 ++ notes | 5 +- 5 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 day23.py create mode 100644 inputs/input23 create mode 100644 inputs/test_input23_1_0 create mode 100644 inputs/test_input23_2_0 diff --git a/day23.py b/day23.py new file mode 100644 index 0000000..d73c1f4 --- /dev/null +++ b/day23.py @@ -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 diff --git a/inputs/input23 b/inputs/input23 new file mode 100644 index 0000000..da06a79 --- /dev/null +++ b/inputs/input23 @@ -0,0 +1,5 @@ +############# +#...........# +###C#D#D#A### + #B#A#B#C# + ######### diff --git a/inputs/test_input23_1_0 b/inputs/test_input23_1_0 new file mode 100644 index 0000000..6a7120d --- /dev/null +++ b/inputs/test_input23_1_0 @@ -0,0 +1,5 @@ +############# +#...........# +###B#C#B#D### + #A#D#C#A# + ######### diff --git a/inputs/test_input23_2_0 b/inputs/test_input23_2_0 new file mode 100644 index 0000000..6a7120d --- /dev/null +++ b/inputs/test_input23_2_0 @@ -0,0 +1,5 @@ +############# +#...........# +###B#C#B#D### + #A#D#C#A# + ######### diff --git a/notes b/notes index 5df1aaa..b633ac4 100644 --- a/notes +++ b/notes @@ -1,3 +1,2 @@ -5425 -5570 -5578 +12521 +