Co-authored-by: Mikael CAPELLE <mikael.capelle@thalesaleniaspace.com> Co-authored-by: Mikaël Capelle <capelle.mikael@gmail.com> Reviewed-on: #3
44 lines
1.4 KiB
Python
44 lines
1.4 KiB
Python
from collections import Counter
|
|
from typing import Any, Iterator, Literal
|
|
|
|
from ..base import BaseSolver
|
|
|
|
|
|
def generator_rating(
|
|
values: list[str], most_common: bool, default: Literal["0", "1"]
|
|
) -> str:
|
|
index = 0
|
|
most_common_idx = 0 if most_common else 1
|
|
|
|
while len(values) > 1:
|
|
cnt = Counter(value[index] for value in values)
|
|
bit = cnt.most_common(2)[most_common_idx][0]
|
|
if cnt["0"] == cnt["1"]:
|
|
bit = default
|
|
values = [value for value in values if value[index] == bit]
|
|
index += 1
|
|
|
|
return values[0]
|
|
|
|
|
|
class Solver(BaseSolver):
|
|
def solve(self, input: str) -> Iterator[Any]:
|
|
lines = input.splitlines()
|
|
|
|
# part 1
|
|
most_and_least_common = [
|
|
tuple(
|
|
Counter(line[col] for line in lines).most_common(2)[m][0]
|
|
for m in range(2)
|
|
)
|
|
for col in range(len(lines[0]))
|
|
]
|
|
gamma_rate = int("".join(most for most, _ in most_and_least_common), base=2)
|
|
epsilon_rate = int("".join(least for _, least in most_and_least_common), base=2)
|
|
yield gamma_rate * epsilon_rate
|
|
|
|
# part 2
|
|
oxygen_generator_rating = int(generator_rating(lines, True, "1"), base=2)
|
|
co2_scrubber_rating = int(generator_rating(lines, False, "0"), base=2)
|
|
yield oxygen_generator_rating * co2_scrubber_rating
|