-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDay14.py
More file actions
144 lines (112 loc) · 4.49 KB
/
Day14.py
File metadata and controls
144 lines (112 loc) · 4.49 KB
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
134
135
136
137
138
139
140
141
142
143
144
import Utility
filePath = 'input/day14/part1.txt'
def increasePairCount(pairCount, pair, amount=1):
existingValue = pairCount.get(pair, 0)
pairCount.update({pair: existingValue + amount})
class Rules:
def __init__(self) -> None:
inputLines = Utility.getLinesFromFile(filePath)
self.rules = {}
for l in inputLines[2:]:
pair, output = l.split(' -> ')
l, r = pair
self.rules.update({(l, r): output})
def applyRules(self, polymer):
result = []
for i in range(len(polymer) - 1):
pair = (polymer[i], polymer[i + 1])
ruleOutput = self.rules.get(pair)
result.append(pair[0])
if(ruleOutput != None):
result.append(ruleOutput)
result.append(polymer[len(polymer) - 1])
return ''.join(result)
def applyRulesToPairCount(self, pairCount):
newPairCount = {}
for pair, count in pairCount.items():
ruleOutput = self.rules.get(pair)
if ruleOutput == None:
increasePairCount(newPairCount, pair, count)
else:
increasePairCount(newPairCount, (pair[0], ruleOutput), count)
increasePairCount(newPairCount, (ruleOutput, pair[1]), count)
return newPairCount
def createNStepLookup(self, stepSize) -> dict[tuple[str, str], str]:
letterSet = set()
lookup = {}
for rule in self.rules.items():
letterSet.add(rule[0][0])
letterSet.add(rule[0][1])
for left in letterSet:
for right in letterSet:
polymer = left + right
for i in range(stepSize):
polymer = self.applyRules(polymer)
lookup.update({(left, right): polymer})
return lookup
def applyLookup(self, lookup, polymer):
result = []
for i in range(len(polymer) - 1):
pair = (polymer[i], polymer[i + 1])
ruleOutput = lookup.get(pair)
result.append(pair[0])
if(ruleOutput != None):
result.append(ruleOutput)
result.append(polymer[len(polymer) - 1])
return ''.join(result)
def efficientIterate(self, stepSize, stepCount, polymer):
lookup = self.createNStepLookup(stepSize)
for i in range(stepCount):
print(i)
polymer = self.applyLookup(lookup, polymer)
return polymer
def findMostAndLeastCommonCount(polymer):
counts = {}
for c in polymer:
existingValue = counts.get(c, 0)
counts.update({c: existingValue + 1})
return Utility.maxBy(counts.items(), lambda item: item[1]), Utility.minBy(counts.items(), lambda item: item[1])
def findMostAndLeastCommonFromPairCount(pairCount):
inputLines = Utility.getLinesFromFile(filePath)
initialPolymer = inputLines[0]
counts = {}
for pair, count in pairCount.items():
# Only update with left element of each pair to prevent double counting
existingValue = counts.get(pair[0], 0)
counts.update({pair[0]: existingValue + count})
# add in last element of polymer (which will be last element of initial polymer) to compensate it not being a left element
lastChar = initialPolymer[-1]
existingValue = counts.get(lastChar, 0)
counts.update({lastChar: existingValue + 1})
return Utility.maxBy(counts.items(), lambda item: item[1]), Utility.minBy(counts.items(), lambda item: item[1])
def initializePairSetFromFile():
inputLines = Utility.getLinesFromFile(filePath)
polymer = inputLines[0]
pairCount = {}
for i in range(len(polymer) - 1):
pL, pR = polymer[i:i+2]
increasePairCount(pairCount, (pL, pR))
return pairCount
def solvePart1():
rules = Rules()
inputLines = Utility.getLinesFromFile(filePath)
polymer = inputLines[0]
for i in range(10):
polymer = rules.applyRules(polymer)
mostCommon, leastCommon = findMostAndLeastCommonCount(polymer)
print('Solution to part1:')
print(polymer)
print(mostCommon, leastCommon)
print(mostCommon[1] - leastCommon[1])
def solvePart2():
rules = Rules()
pairCount = initializePairSetFromFile()
for i in range(40):
pairCount = rules.applyRulesToPairCount(pairCount)
mostCommon, leastCommon = findMostAndLeastCommonFromPairCount(pairCount)
print('Solution to part2:')
print(mostCommon, leastCommon)
print(mostCommon[1] - leastCommon[1])
if(__name__ == '__main__'):
solvePart1()
solvePart2()