116 lines
3.9 KiB
Python
Executable File
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])
|