advent-of-code/2021/day03_gamma.py

95 lines
2.3 KiB
Python

from collections import defaultdict
def main(filename: str, expected_part_1: int = None, expected_part_2: int = None):
print(f"\n+ Running on {filename}")
with open(filename) as f:
data = f.read().strip().split("\n")
counter_part_1 = solve_part_1(data)
print(f"1. Found {counter_part_1}")
if expected_part_1:
assert expected_part_1 == counter_part_1
counter_part_2 = solve_part_2(data)
print(f"2. Found {counter_part_2}")
if expected_part_2:
assert expected_part_2 == counter_part_2
def solve_part_1(data):
count_ones = defaultdict(int)
total = len(data)
for binary in data:
for index, digit in enumerate(binary):
if digit == "1":
count_ones[index] += 1
gamma = ""
epsilon = ""
for index in range(len(data[0])):
most_common = _most_common(count_ones, total, index)
gamma += most_common
epsilon += "0" if most_common == "1" else "1"
return int(gamma, 2) * int(epsilon, 2)
def _most_common(count_ones, total, index):
"""
Return 1 if the most common value is 1, otherwise 0.
"""
if count_ones[index] >= total / 2:
return "1"
return "0"
def solve_part_2(data):
oxygen = _oxygen(data)
co2 = _co2(data)
return oxygen * co2
def _oxygen(data):
index = 0
max_index = len(data[0])
while index < max_index:
if len(data) == 1:
return int(data[0], 2)
ones, zeros = _separate_ones_zeros(data, index)
index += 1
if len(ones) >= len(zeros):
data = ones
else:
data = zeros
return int(data[0], 2)
def _co2(data):
index = 0
max_index = len(data[0])
while index < max_index:
if len(data) == 1:
return int(data[0], 2)
ones, zeros = _separate_ones_zeros(data, index)
index += 1
if len(ones) < len(zeros):
data = ones
else:
data = zeros
def _separate_ones_zeros(data, index):
ones = []
zeros = []
for binary in data:
if binary[index] == "1":
ones.append(binary)
else:
zeros.append(binary)
return ones, zeros
if __name__ == "__main__":
main("inputs/day03-test1", expected_part_1=198, expected_part_2=230)
main("inputs/day03", expected_part_1=1997414, expected_part_2=1032597)