-
Notifications
You must be signed in to change notification settings - Fork 0
/
day7.py
136 lines (107 loc) · 3.91 KB
/
day7.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
class Program(object):
def __init__(self, name, weight):
self.children = set()
self.weight = weight
self.name = name
self.balanced = True
self.totalWeight = self.weight
def addChild(self, child):
self.children.add(child)
def __eq__(self, other):
if isinstance(other, self.__class__):
return other.name == self.name
else:
return False
def _ne__(self, other):
return not self.__eq__(other)
def __hash__(self):
return self.name.__hash__()
Programs = set()
AllLines = []
AllPrograms = {}
def readInput(file):
with open(file, "r") as f:
for eachLine in f:
eachLine = eachLine.strip()
AllLines.append(eachLine)
def process():
for eachLine in AllLines:
parsed = parseEachLine(eachLine)
if parsed[0] in Programs:
Programs.remove(parsed[0])
else:
Programs.add(parsed[0])
for eachTop in parsed[2]:
if eachTop in Programs:
Programs.remove(eachTop)
else:
Programs.add(eachTop)
def buildGraph():
for eachLine in AllLines:
parsed = parseEachLine(eachLine)
AllPrograms[parsed[0]] = Program(parsed[0], parsed[1])
for eachLine in AllLines:
parsed = parseEachLine(eachLine)
thisProgram = AllPrograms[parsed[0]]
if len(parsed[2]) != 0:
for eachChild in parsed[2]:
thisProgram.addChild(AllPrograms[eachChild])
def processGraph():
root = AllPrograms["vtzay"] #found this in part 1
processTotalWeight(root)
baseWeight = list(filter(lambda c: c.balanced, root.children))[0].totalWeight
unbalancedWeight = list(filter(lambda c: not c.balanced, root.children))[0].totalWeight
offset = baseWeight - unbalancedWeight
return findCorrectedWeight(root, offset)
def processTotalWeight(node):
for eachChild in node.children:
processTotalWeight(eachChild)
node.totalWeight += eachChild.totalWeight
node.balanced = node.balanced and eachChild.balanced
if node.balanced and len(node.children) > 0:
allChildrenWeights = [child.totalWeight for child in node.children]
node.balanced = max(allChildrenWeights) == min(allChildrenWeights)
def findCorrectedWeight(node, offset):
weights = []
for eachChild in node.children:
weights.append(eachChild.weight)
if not eachChild.balanced:
return findCorrectedWeight(eachChild, offset)
# if here, that means I am marked as not Balanced but all my children are balance. That means,
# one of my children has a weight that is off by offset.
return findOutlinerChild(node).weight + offset
def findOutlinerChild(node):
weights = {}
for eachChild in node.children:
if weights.get(eachChild.totalWeight, None) == None:
weights[eachChild.totalWeight] = [eachChild]
else:
weights.get(eachChild.totalWeight).append(eachChild)
for eachWeight in weights.values():
if len(eachWeight) == 1:
return eachWeight[0]
return None
def parseEachLine(eachLine):
bottomPart = eachLine
topNames = []
if "->" in eachLine:
arrowIndex = eachLine.index("->")
bottomPart = bottomPart[0:arrowIndex-1]
topPart = eachLine[arrowIndex+3:].strip()
for eachTop in topPart.split(","):
topNames.append(eachTop.strip())
bottomWeightIdx = bottomPart.index("(")
bottomName = bottomPart[0:bottomWeightIdx-1]
bottomWeight = int(bottomPart[bottomWeightIdx+1:-1])
return (bottomName, bottomWeight, topNames)
#print(parseEachLine("dihjv (2158) -> gausx, ncdmp, hozgrub"))
#print(parseEachLine("eauol (56)"))
def Solution1():
readInput("day7Input.txt")
process()
print(Programs)
def Solution2():
readInput("day7Input.txt")
buildGraph()
return processGraph()
print(Solution2())