From 3e35e6caf94c2178abe1a30ea8b8f867428d6a45 Mon Sep 17 00:00:00 2001 From: daviddoji Date: Sat, 5 Mar 2022 15:18:35 +0100 Subject: [PATCH] Solution to problem 6 part 1 in Python --- src/Year_2017/P6.py | 100 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 src/Year_2017/P6.py diff --git a/src/Year_2017/P6.py b/src/Year_2017/P6.py new file mode 100644 index 0000000..7c6b022 --- /dev/null +++ b/src/Year_2017/P6.py @@ -0,0 +1,100 @@ +# --- Day 6: Memory Reallocation --- + +# A debugger program here is having an issue: it is trying to repair a memory +# reallocation routine, but it keeps getting stuck in an infinite loop. + +# In this area, there are sixteen memory banks; each memory bank can hold any +# number of blocks. The goal of the reallocation routine is to balance the +# blocks between the memory banks. + +# The reallocation routine operates in cycles. In each cycle, it finds the +# memory bank with the most blocks (ties won by the lowest-numbered memory +# bank) and redistributes those blocks among the banks. To do this, it removes +# all of the blocks from the selected bank, then moves to the next (by index) +# memory bank and inserts one of the blocks. It continues doing this until it +# runs out of blocks; if it reaches the last memory bank, it wraps around to +# the first one. + +# The debugger would like to know how many countss can be done before a +# blocks-in-banks configuration is produced that has been seen before. + +# For example, imagine a scenario with only four memory banks: + +# The banks start with 0, 2, 7, and 0 blocks. The third bank has the most +# blocks, so it is chosen for counts. +# Starting with the next bank (the fourth bank) and then continuing to the +# first bank, the second bank, and so on, the 7 blocks are spread out over the +# memory banks. The fourth, first, and second banks get two blocks each, and +# the third bank gets one back. The final result looks like this: 2 4 1 2. +# Next, the second bank is chosen because it contains the most blocks +# (four). Because there are four memory banks, each gets one block. The result +# is: 3 1 2 3. +# Now, there is a tie between the first and fourth memory banks, both of +# which have three blocks. The first bank wins the tie, and its three blocks +# are distributed evenly over the other three banks, leaving it with none: +# 0 2 3 4. +# The fourth bank is chosen, and its four blocks are distributed such that +# each of the four banks receives one: 1 3 4 1. +# The third bank is chosen, and the same thing happens: 2 4 1 2. + +# At this point, we've reached a state we've seen before: 2 4 1 2 was already +# seen. The infinite loop is detected after the fifth block counts +# cycle, and so the answer in this example is 5. + +# Given the initial block counts in your puzzle input, how many counts +# cycles must be completed before a configuration is produced that has been +# seen before? + +from collections import Counter, defaultdict +from itertools import cycle, islice + +with open("files/P6.txt") as f: + values = [int(num) for num in f.read().strip().split()] + +banks = defaultdict(int) +for idx, value in enumerate(values): + banks[str(idx)] = value + + +def cycle_through(dic: dict[str, int], starting: int, times: int) -> list[str]: + keys = list(dic.keys()) + cycled = cycle(keys) + + if starting == len(keys): + starting = 0 + + return list( + islice( + cycled, + keys.index(str(starting)), + keys.index(str(starting)) + times, + ) + ) + + +def part_1() -> None: + seen = [] + repeated = False + iteration = 0 + while not repeated: + iteration += 1 + counts = Counter(banks).most_common() + # get the most common (tuple) + _most_common = counts[0] + # reset its key + banks[_most_common[0]] = 0 + for key in cycle_through( + banks, int(_most_common[0]) + 1, int(_most_common[1]) + ): + banks[key] += 1 + _iter = Counter(banks).most_common() + if _iter in seen: + repeated = True + else: + seen.append(_iter) + + print(f"{iteration} cycles must be completed") + + +if __name__ == "__main__": + part_1()