82 lines
3.4 KiB
Python
Executable File
82 lines
3.4 KiB
Python
Executable File
#!/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")
|