Solution to problem 6 part 1 in Python

This commit is contained in:
David Doblas Jiménez 2022-03-05 15:18:35 +01:00
parent a14b73ad1b
commit 3e35e6caf9

100
src/Year_2017/P6.py Normal file
View File

@ -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()