Solve 2017/07
This commit is contained in:
parent
5f533ff1ad
commit
416adc5747
3 changed files with 1545 additions and 0 deletions
1416
2017/07/input.txt
Normal file
1416
2017/07/input.txt
Normal file
File diff suppressed because it is too large
Load diff
116
2017/07/solve.py
Normal file
116
2017/07/solve.py
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
import re
|
||||
import sys
|
||||
|
||||
# PART 1
|
||||
|
||||
def any_key(d):
|
||||
return list(d)[0]
|
||||
|
||||
class Tower:
|
||||
PROG_RE = r"(\S+) \((\d+)\)( -> (.*))?\n"
|
||||
|
||||
def __init__(self, weight_of, children_of, parent_of):
|
||||
self.wo = weight_of
|
||||
self.co = children_of
|
||||
self.po = parent_of
|
||||
|
||||
@classmethod
|
||||
def from_file(cls, filename):
|
||||
weight_of = {} # name -> weight
|
||||
children_of = {} # name -> children
|
||||
parent_of = {} # name -> parent
|
||||
|
||||
with open(filename, "r") as f:
|
||||
for line in f:
|
||||
match = re.fullmatch(cls.PROG_RE, line)
|
||||
|
||||
name = match.group(1)
|
||||
weight = int(match.group(2))
|
||||
if match.group(4):
|
||||
children = match.group(4).split(", ")
|
||||
else:
|
||||
children = []
|
||||
|
||||
weight_of[name] = weight
|
||||
children_of[name] = children
|
||||
for child in children:
|
||||
parent_of[child] = name
|
||||
|
||||
return cls(weight_of, children_of, parent_of)
|
||||
|
||||
def find_root(self):
|
||||
program = any_key(self.po)
|
||||
while program in self.po:
|
||||
program = self.po[program]
|
||||
return program
|
||||
|
||||
# PART 2
|
||||
|
||||
# This part is implemented really shitty. It makes a lot of assumptions and
|
||||
# will probably break the second the input changes or you're just unlucky.
|
||||
# For my particular input, it worked though.
|
||||
#
|
||||
# The basic idea of the algorithm is:
|
||||
#
|
||||
# 1. Find the plate where one branch has a different weight from all the others
|
||||
# 2. Find out which branch weight is wrong and whic weights are correct
|
||||
# 3. Fix the branch's root program's weight
|
||||
|
||||
def weight(self, name):
|
||||
return self.wo[name] + sum(self.weight(c) for c in self.co[name])
|
||||
|
||||
def balanced(self, name):
|
||||
cs = self.co[name]
|
||||
ws = [self.weight(c) for c in cs]
|
||||
return min(ws) == max(ws)
|
||||
|
||||
def unbalanced_child(self, name):
|
||||
for c in self.co[name]:
|
||||
if not self.balanced(c):
|
||||
return c
|
||||
|
||||
def find_imbalance(self, name):
|
||||
c = self.unbalanced_child(name)
|
||||
if c is None:
|
||||
weights = [(c, self.weight(c)) for c in self.co[name]]
|
||||
return weights
|
||||
else:
|
||||
return self.find_imbalance(c)
|
||||
|
||||
def fix_imbalance(self, weights):
|
||||
# Which weight do we need to correct?
|
||||
ws = [weight for (c, weight) in weights]
|
||||
if ws.count(max(ws)) < ws.count(min(ws)):
|
||||
weight = max(ws)
|
||||
other = min(ws)
|
||||
else:
|
||||
weight = min(ws)
|
||||
other = max(ws)
|
||||
|
||||
# Wich program has that weight?
|
||||
prog = None
|
||||
for (p, w) in weights:
|
||||
if w == weight:
|
||||
prog = p
|
||||
break
|
||||
|
||||
# w_prog_soll - w_prog = w_soll - w_branch
|
||||
# w_prog_soll = w_soll - w_branch + w_prog
|
||||
# w_prog_soll = w_soll - (w_branch - w_prog)
|
||||
w_prog = self.wo[prog]
|
||||
w_soll = other
|
||||
w_branch = self.weight(prog)
|
||||
return w_soll - (w_branch - w_prog)
|
||||
|
||||
def main(filename):
|
||||
print(f"Solutions for {filename}")
|
||||
tower = Tower.from_file(filename)
|
||||
root = tower.find_root()
|
||||
print(f"Part 1: {root}")
|
||||
weights = tower.find_imbalance(root)
|
||||
fixed = tower.fix_imbalance(weights)
|
||||
print(f"Part 2: {fixed}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
for filename in sys.argv[1:]:
|
||||
main(filename)
|
||||
13
2017/07/test_input.txt
Normal file
13
2017/07/test_input.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
pbga (66)
|
||||
xhth (57)
|
||||
ebii (61)
|
||||
havc (66)
|
||||
ktlj (57)
|
||||
fwft (72) -> ktlj, cntj, xhth
|
||||
qoyq (66)
|
||||
padx (45) -> pbga, havc, qoyq
|
||||
tknk (41) -> ugml, padx, fwft
|
||||
jptl (61)
|
||||
ugml (68) -> gyxo, ebii, jptl
|
||||
gyxo (61)
|
||||
cntj (57)
|
||||
Loading…
Add table
Add a link
Reference in a new issue