Sean McLemon | Advent of Code

Home | Czech | Blog | GitHub | Advent Of Code | Notes


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