118 lines
2.6 KiB
Python
118 lines
2.6 KiB
Python
![]() |
import sys
|
||
|
sys.path.append('../lib')
|
||
|
|
||
|
import tools, re
|
||
|
|
||
|
COLORS = ['red', 'green', 'blue']
|
||
|
|
||
|
class Game(object):
|
||
|
def __init__(self, inp):
|
||
|
s = inp.split(':')
|
||
|
self.id = int(s[0].split()[1])
|
||
|
matches = s[1].split(';')
|
||
|
self.matches = []
|
||
|
for match_desc in matches:
|
||
|
m = Match(match_desc)
|
||
|
self.matches.append(m)
|
||
|
|
||
|
def __str__(self):
|
||
|
out = f'Game ID: {self.id}\n'
|
||
|
for m in self.matches:
|
||
|
out += m.__str__()
|
||
|
return out
|
||
|
|
||
|
def get_id(self) -> int:
|
||
|
return self.id
|
||
|
|
||
|
def possible_for_limits(self, limits: dict) -> bool:
|
||
|
for m in self.matches:
|
||
|
if not m.possible_for_limits(limits):
|
||
|
return False
|
||
|
return True
|
||
|
|
||
|
def get_fewest_possible_power(self) -> int:
|
||
|
required = self._get_fewest_possible_cubes()
|
||
|
power = 1
|
||
|
for c in COLORS:
|
||
|
try:
|
||
|
n = required[c]
|
||
|
except KeyError:
|
||
|
continue
|
||
|
if n > 0:
|
||
|
power *= n
|
||
|
return power
|
||
|
|
||
|
|
||
|
def _get_fewest_possible_cubes(self):
|
||
|
required = dict(zip(COLORS, [0 for _ in range(len(COLORS))]))
|
||
|
for m in self.matches:
|
||
|
for c in COLORS:
|
||
|
try:
|
||
|
need = m.cubes[c]
|
||
|
except KeyError:
|
||
|
continue
|
||
|
required[c] = max(required[c], need)
|
||
|
return required
|
||
|
|
||
|
|
||
|
class Match(object):
|
||
|
def __init__(self, inp):
|
||
|
self.cubes = dict()
|
||
|
for s in inp.split(', '):
|
||
|
s = s.split()
|
||
|
self.cubes[s[1]] = int(s[0])
|
||
|
|
||
|
def __str__(self):
|
||
|
out = 'Match: '
|
||
|
for k, v in self.cubes.items():
|
||
|
out += f'{k}: {v} '
|
||
|
out += '\n'
|
||
|
return out
|
||
|
|
||
|
def possible_for_limits(self, limits: dict) -> bool:
|
||
|
for color, want in self.cubes.items():
|
||
|
try:
|
||
|
have = limits[color]
|
||
|
except KeyError:
|
||
|
return False
|
||
|
if have < want:
|
||
|
return False
|
||
|
return True
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
def solve1(lines):
|
||
|
total = 0
|
||
|
limits = {
|
||
|
'red': 12,
|
||
|
'green': 13,
|
||
|
'blue': 14,
|
||
|
}
|
||
|
for l in lines:
|
||
|
game = Game(l)
|
||
|
if game.possible_for_limits(limits):
|
||
|
total += game.get_id()
|
||
|
return total
|
||
|
|
||
|
def solve2(lines):
|
||
|
total = 0
|
||
|
for l in lines:
|
||
|
g = Game(l)
|
||
|
power = g.get_fewest_possible_power()
|
||
|
total += power
|
||
|
return total
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
r = tools.Reader('input.txt')
|
||
|
lines = r.read()
|
||
|
|
||
|
x = solve1(lines)
|
||
|
print(x)
|
||
|
|
||
|
y = solve2(lines)
|
||
|
print(y)
|
||
|
|
||
|
|