2021-12-03 - Binary Diagnostic
(original .ipynb)
Day 3 puzzle input is a list of binary numbers (mine is here). Part 1 involves finding the most and common values in each bit position and using these to produce "gamma" and "epsilon" values, and finding the product of these. Part 2 involves combing through the list of binary numbers, finding the most/least common digit in each position and repeatedly filtering this to produce "oxygen generator rating" (from the most common) and the "co2 scrubber rating" (from the least common) - and again finding the product of these two numbers.
puzzle_input_str = open("puzzle_input/day3.txt").read()
test_input_str = """00100
11110
10110
10111
10101
01111
00111
11100
10000
11001
00010
01010"""
from collections import defaultdict
def parse_line(line):
return list(line)
def parse_input_lines(input_str):
return [parse_line(line) for line in input_str.split("\n")]
def sorted_positions(numbers, position):
positions = defaultdict(lambda: 0)
for number in numbers:
positions[number[position]] += 1
if positions["1"] >= positions["0"]:
return ("1", "0")
return ("0", "1")
def part_one(input_str):
numbers = parse_input_lines(input_str)
gamma = []
epsilon = []
for i in range(len(numbers[0])):
most, least = sorted_positions(numbers, i)
gamma.append(most)
epsilon.append(least)
return int("".join(gamma), 2) * int("".join(epsilon), 2)
assert 198 == part_one(test_input_str)
print("part one:", part_one(puzzle_input_str))
part one: 1307354
def part_two(input_str):
numbers = parse_input_lines(input_str)
o2 = numbers.copy()
co2 = numbers.copy()
for position in range(len(numbers[0])):
if len(o2) > 1:
most_o2, _ = sorted_positions(o2, position)
o2 = [n for n in o2 if n[position] == most_o2]
if len(co2) > 1:
_, least_co2 = sorted_positions(co2, position)
co2 = [n for n in co2 if n[position] == least_co2]
return int("".join(o2[0]), 2) * int("".join(co2[0]), 2)
assert 230 == part_two(test_input_str)
print("part two:", part_two(puzzle_input_str))
part two: 482500