From da96bf0fb984fa0fb5a7459e3b195d33207cb0db Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Sun, 22 May 2022 15:19:54 +0000 Subject: [PATCH] feat: solve day 23 part 2 --- 23/main.py | 58 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/23/main.py b/23/main.py index 3a9c2f2..4d12d1e 100644 --- a/23/main.py +++ b/23/main.py @@ -23,8 +23,10 @@ def simulate(cups: list[int], moves: int): current_cup_label = cups[0] for _ in range(moves): + # take 3 cups taken_cups = take_cups(cups, cups.index(current_cup_label)+1, 3) + # determine destination cup destination_label = current_cup_label - 1 while destination_label not in cups: destination_label -= 1 @@ -32,10 +34,40 @@ def simulate(cups: list[int], moves: int): destination_label = max_value destination = cups.index(destination_label) + # put back the 3 taken cups put_cups(cups, destination + 1, taken_cups) + # move current cup current_cup_label = cups[(cups.index(current_cup_label) + 1) % len(cups)] +def simulate_lookup(next_cup_lookup: list[int], current_cup: int, moves: int): + max_value = len(next_cup_lookup) - 1 + min_value = 1 + + for _ in range(moves): + # take 3 cups + taken_cup1 = next_cup_lookup[current_cup] + taken_cup2 = next_cup_lookup[taken_cup1] + taken_cup3 = next_cup_lookup[taken_cup2] + + # determine destination cup + destination = current_cup + while True: + destination -= 1 + if destination < min_value: + destination = max_value + if destination != taken_cup1 and destination != taken_cup2 and destination != taken_cup3: + break + + # put back the 3 taken cups + next_cup_lookup[current_cup] = next_cup_lookup[taken_cup3] + after_destination = next_cup_lookup[destination] + next_cup_lookup[taken_cup3] = after_destination + next_cup_lookup[destination] = taken_cup1 + + # move current cup + current_cup = next_cup_lookup[current_cup] + def part1(cups: list[int]) -> str: simulate(cups, 100) @@ -43,18 +75,28 @@ def part1(cups: list[int]) -> str: return "".join(map(str, cups[num1_index+1:])) + "".join(map(str, cups[:num1_index])) def part2(cups: list[int]) -> int: - for value in range(max(cups), 1_000_000 + 1): - cups.append(value) + # create lookup table for the next value + next_cup_lookup: list[int] = [0]*(len(cups)+1) + max_value = max(cups) + cups.append(max_value+1) + for i in range(len(cups)-1): + cup = cups[i] + next_cup = cups[i+1] + next_cup_lookup[cup] = next_cup - simulate(cups, 1_00) - # simulate(cups, 10_000_000) + for next_cup in range(max_value+2, 1_000_000+1): + next_cup_lookup.append(next_cup) + next_cup_lookup.append(cups[0]) - num1_index = cups.index(1) - star1 = cups[(num1_index + 1) % len(cups)] - star2 = cups[(num1_index + 2) % len(cups)] + # perform the simulation + simulate_lookup(next_cup_lookup, cups[0], 10_000_000) + + # calculate the final result + star1 = next_cup_lookup[1] + star2 = next_cup_lookup[star1] return star1 * star2 if __name__ == "__main__": - cups = read_input("test.txt") + cups = read_input("input.txt") print("part1: ", part1(cups.copy())) print("part2: ", part2(cups.copy()))