From e2c797cf55421f5366af9276d4f26eb684f3f997 Mon Sep 17 00:00:00 2001 From: dusk Date: Sat, 26 Jul 2025 17:59:33 +0000 Subject: [PATCH] completed 2017.06.2 --- 2017/06/2memory-balance.py | 81 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100755 2017/06/2memory-balance.py diff --git a/2017/06/2memory-balance.py b/2017/06/2memory-balance.py new file mode 100755 index 0000000..42d975f --- /dev/null +++ b/2017/06/2memory-balance.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 + +# this one seems fun! +# i have 16 memory banks, each with a number of blocks. +# every cycle, the banks are re-balanced according to the following: +# - the bank with the greatest number of blocks is the candidate to balance. +# - ties are broken by bank index: lowest wins candidacy. +# - remove all blocks from candidate bank, redistributing them +# one to each following bank (by index no.), wrapping at the end. +# - the candidate bank will only balance BACK to itself if it wraps. +# that is, make sure to re-balance starting from the NEXT bank. +# my puzzle is to solve after how many cycles will the banks be in +# a familiar state. that is, how many cycles in the cycle? +# i can number bank states as: +# - given input state is bank state 0 +# - each following state is incremented by +1, so that state n +# represents the bank state after n cycles are completed. + +if __name__ == '__main__': + def strings_to_ints(data): + for i in range(len(data)): + data[i] = int(data[i]) + return data + + def process_input(file): + list_of_strings = file.read().split() + list_of_ints = strings_to_ints(list_of_strings) + return list_of_ints + + def find_greatest(ints): + index_of_greatest = 0 + for i in range(len(ints)): + if ints[i] > ints[index_of_greatest]: + index_of_greatest = i + return index_of_greatest + + def rebalance(ints): + candidate = find_greatest(ints) + to_rebalance = ints[candidate] + print(f'rebalancing the {candidate}th (i.e. {to_rebalance}) from {ints}...') + new_ints = [] + for int in ints: + new_ints.append(int) + new_ints[candidate] = 0 + for i in range(to_rebalance): + target_index = candidate + i + 1 # since i is between 0 and (to_rebalance - 1) incl. + target_index = target_index % len(new_ints) + new_ints[target_index] = new_ints[target_index] + 1 + # what the fuck. why does bankstate get updated. huh + # after changing my simple new_ints = ints to a for-loop builder + # thing, the shit just fucking works. huh?? clearly the = operator + # isn't JUST a variable assignment button. something is afoot..... + print(f'rebalanced as {new_ints}') + return new_ints + + def check_duplicate(intses): + has_duplicate = False + latest_ints = intses[len(intses)-1] + duplicate_index = '' + for i in range(len(intses)-1): # don't check final index. lol + if intses[i] == latest_ints: + has_duplicate = True + duplicate_index = i + return [has_duplicate,duplicate_index] + +# the main script! +# + with open('input', 'r', encoding='utf-8') as file: + bankstate = [process_input(file)] + print(f'initialized bankstate as {bankstate}') + + seen_before = False + cycles = 0 # initialize cycles counter. this matches current bankstate index + while not seen_before: + cycles += 1 # happy new cycles! *confetti* + last_state = bankstate[len(bankstate)-1] # note: bankstate's max index is cycles-1 currently + new_state = rebalance(last_state) + bankstate.append(new_state) + [seen_before, duplicate_index] = check_duplicate(bankstate) + print(f"we looped after {cycles} cycles! that's a lot... i'm so dizzy....") + print(f"this state last seen at index {duplicate_index}, i.e. the loop has {cycles-duplicate_index} cycles")