Some notes that I thought would be worth mentioning up front:
- Advent of Code randomizes the input for each user, with the input format being 1,000 12-digit binary numbers delimited by newlines.
- I've verified that my solution works by submitting the generated answer on the website.
Here is the important part of the problem statement, transcribed from Day 3 - Advent of Code 2021:
You need to use the binary numbers in the diagnostic report to generate two new binary numbers (called the gamma rate and the epsilon rate). The power consumption can then be found by multiplying the gamma rate by the epsilon rate.
Each bit in the gamma rate can be determined by finding the most common bit in the corresponding position of all numbers in the diagnostic report. For example, given the following diagnostic report:
00100 11110 10110 10111 10101 01111 00111 11100 10000 11001 00010 01010
Considering only the first bit of each number, there are five
0bits and seven
1bits. Since the most common bit is
1, the first bit of the gamma rate is
The most common second bit of the numbers in the diagnostic report is
0, so the second bit of the gamma rate is
The most common value of the third, fourth, and fifth bits are
0, respectively, and so the final three bits of the gamma rate are
So, the gamma rate is the binary number
The epsilon rate is calculated in a similar way; rather than use the most common bit, the least common bit from each position is used. So, the epsilon rate is
9in decimal. Multiplying the gamma rate (
22) by the epsilon rate (
9) produces the power consumption,
Use the binary numbers in your diagnostic report to calculate the gamma rate and epsilon rate, then multiply them together. What is the power consumption of the submarine? (Be sure to represent your answer in decimal, not binary.)
#!/usr/bin/env python3 from pathlib import Path def load_numbers(input_path: Path) -> list[int]: with input_path.open() as f: return [ int(binary_string, 2) for line in f if (binary_string := line.strip()) ] def binary_diagnostic_part_one(input_path: Path) -> int: NUM_BINARY_DIGITS = 12 zero_counts =  * NUM_BINARY_DIGITS # used to flip all bits in gamma rate to get epsilon rate BIT_MASK = 2 ** NUM_BINARY_DIGITS - 1 # 0b1111_1111_1111 numbers = load_numbers(input_path) for number in numbers: for i in range(NUM_BINARY_DIGITS): binary_digit = (number >> i) & 1 zero_counts[i] += int(binary_digit == 0) # calculate gamma rate from zero counts # starting from MSB -> LSB n = len(numbers) gamma_rate = 0 for num_zeros in reversed(zero_counts): gamma_digit = 0 if num_zeros > n - num_zeros else 1 gamma_rate = (gamma_rate << 1) | gamma_digit epsilon_rate: int = gamma_rate ^ BIT_MASK return gamma_rate * epsilon_rate if __name__ == "__main__": print(binary_diagnostic_part_one(Path("input.txt")))
A pared-down version of the actual input.txt, for brevity.
010110011101 101100111000 100100000011 111000010001 001100010011 010000111100 001000100011 001000100111 010001111110 111101001011 011000101011