#!/usr/bin/env python3 import copy import sys from typing import Sequence def part1(lines: Sequence[int], bits=12): gamma = 0 epsilon = 0 for bit in range(bits): mask = 1 << (bits - bit - 1) ones = 0 for line in lines: if mask & line: ones += 1 zeroes = len(lines) - ones if ones > zeroes: gamma |= mask else: epsilon |= mask # Fun thing - epsilon rate is just the inversion of the gamma rate. # However, python doesn't seem to support signed inversion so we just calculate it above. boo print(f"gamma: {gamma} {bin(gamma)}") print(f"epsilon: {epsilon} {bin(epsilon)}") print(f"product: {gamma * epsilon}") def part2(lines: Sequence[int], bits=12): oxygen = copy.deepcopy(lines) carbon = copy.deepcopy(lines) for bit in range(bits): # Find the most common bit if len(oxygen) > 1: mask = 1 << (bits - bit - 1) ones = 0 for line in oxygen: if mask & line: ones += 1 zeroes = len(oxygen) - ones if ones >= zeroes: # Filter out oxygen numbers that don't have a 1 in this position oxygen = [line for line in oxygen if line & mask] else: oxygen = [line for line in oxygen if not (line & mask)] # Now do this on the carbon array if len(carbon) > 1: ones = 0 for line in carbon: if mask & line: ones += 1 zeroes = len(carbon) - ones if ones >= zeroes: # Keep the *least* common carbon = [line for line in carbon if not (line & mask)] else: carbon = [line for line in carbon if line & mask] oxygen, = oxygen carbon, = carbon print(f"Oxygen: {oxygen}") print(f"Carbon: {carbon}") print(f"Product: {oxygen * carbon}") lines = [int(line, 2) for line in sys.stdin] print("Part 1") part1(lines) print("Part 2") part2(lines)