adventofcode/2017/07/2recursive-circus.py

116 lines
3.9 KiB
Python
Executable File

#!/usr/bin/env python3
if __name__ == '__main__':
with open('input','r',encoding='utf-8') as file:
all_programs = file.readlines()
i = 0
for program in all_programs:
program = program.split()
program[1] = int(program[1].strip('()'))
if len(program) > 2:
program[2] = []
for j in range(3, len(program)):
program[2].append(program[j].strip(','))
program = [program[0], program[1], program[2]]
else:
program.append([])
all_programs[i] = program
i += 1
# at this point, each line is one program in the stack,
# and each line is a list of info.
# list[0] is the program name.
# list[1] is the program weight.
# list[2] is a list of other programs which sit directly on top.
# for part 1, we simply need to find the program name
# which exists in no other list of children!
# the datatype of all_programs is
# [[string,int,[string, string,...]],[string,int,[string,string,...],...]
def find_position(programs_list):
all_children = ['']
for program in programs_list:
if program[2] == []:
program = program.append("top")
else:
children = program[2]
if all_children == ['']:
all_children = children
else:
all_children = all_children + children
# note: all_children will not have duplicates!
# why? can't stand on two programs' heads at once....
for program in programs_list:
try:
all_children.index(program[0])
except ValueError:
program = program.append("bot")
for program in programs_list:
if len(program) == 3:
program = program.append("mid")
def rename_programs(programs_list):
name_index = []
for program in programs_list:
name_index = name_index + [program[0]]
i = 0
for program in programs_list:
children = program[2]
if children != []:
j = 0
for child in children:
child_index = name_index.index(child)
programs_list[i][2][j] = child_index
j += 1
# rename program itself
programs_list[i][0] = name_index.index(program[0])
i += 1
find_position(all_programs)
i = 0
for program in all_programs:
if program[3] == "bot":
bot_index = i
i += 1
bot_name = all_programs[bot_index][0]
rename_programs(all_programs)
# at this point, all_programs looks like:
# [ [0, 123, [4, 8, 14], 'mid'],
# [1, 51, [] , 'top'],
# [2, 293, [9, 1] , 'mid'],
# ...
# ]
# starting from bot_index, build out the tree.
# recursive functions might be helpful!
# bot and mid programs have child programs.
# all child programs must be balanced such that
# the weight of all children (and grandchildren, etc)
# must be the same.
# starting at bottom, make sure children are balanced.
# if children have children, check that those are balanced,
# then sum the total weight of child and all ITS children,
# making sure that each child is equal.
# this explanation is silly.
# you get it.
def get_weight(programs_list, index):
program = programs_list[index]
weight = program[1]
if( program[3] == "bot") or (program[3] == "mid"):
children = program[2]
children_weight = 0
for child in children:
child_weight = get_weight(programs_list, child)
children_weight += child_weight
weight += children_weight
return weight
print(get_weight(all_programs, bot_index))
i = 0
for i in range(10):
print(all_programs[i])