40 lines
1.2 KiB
Python
40 lines
1.2 KiB
Python
import sys
|
|
from collections import Counter
|
|
from typing import Literal
|
|
|
|
|
|
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]
|
|
|
|
|
|
lines = sys.stdin.read().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)
|
|
print(f"answer 1 is {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)
|
|
answer_2 = oxygen_generator_rating * co2_scrubber_rating
|
|
print(f"answer 2 is {answer_2}")
|