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