From 614bdb6f996b8d3e282a4d7c57f1ddd84239c210 Mon Sep 17 00:00:00 2001 From: Ryan Reed Date: Fri, 3 Dec 2021 16:22:47 -0500 Subject: [PATCH] Initial working version for both parts --- puzzles/day03.py | 114 ++++++++++++++++++++++++++++++++++-------- puzzles/test_day03.py | 13 ++--- 2 files changed, 99 insertions(+), 28 deletions(-) diff --git a/puzzles/day03.py b/puzzles/day03.py index f6e4860..f2675e6 100644 --- a/puzzles/day03.py +++ b/puzzles/day03.py @@ -7,43 +7,117 @@ Run with: import pathlib import sys -from typing import List, Tuple +from typing import Dict, List, Tuple from collections import defaultdict -class Submarine: - gamma: int = 0 - epsilon: int = 0 - power: int = 0 +class Diagnostics: + _most_common = None + report = None + + def __init__(self, report: List[int]) -> None: + self.report = report + self._most_common = self.commonality(report) - def decode_report(self, report: List[int]) -> None: - num_1 = defaultdict(int) - for binary in report: - for index, bit in enumerate(binary): - num_1[index] += int(bit) - total = len(report) + def power_usage(self) -> None: + half_count = len(self.report)/2 gamma = epsilon = "" - for binary in num_1.values(): - if binary > (total/2): + for common in self._most_common: + if common == 1: gamma += "1" epsilon += "0" else: gamma += "0" epsilon += "1" - self.gamma = int(gamma, 2) - self.epsilon = int(epsilon, 2) - self.power = self.gamma * self.epsilon + gamma = int(gamma, 2) + epsilon = int(epsilon, 2) + return gamma * epsilon + + + def calculate_oxygen_generator_rating(self, inputs) -> int: + """ + Bit Criteria: + Most common value in current bit position + If 0 and 1 are equally common, keep values with a 1 + Keep only values with this bit in this position + """ + report = inputs.copy() + for column in range(len(report[0])): + most_common = self.commonality(report) + for binary in list(report): + if (int(binary[column]) != most_common[column] and most_common[column] != 2) or (most_common[column] == 2 and binary[column] != "1"): + report.remove(binary) + + if len(report) == 1: + return int(report[0], 2) + + if len(report) > 1: # May not be necessary + report = self.calculate_oxygen_generator_rating(report) + + return int(report[0], 2) + + + def calculate_co2_scrubber_rating(self, inputs) -> int: + """ + Bit Criteria: + Least common value in current position + If 0 and 1 are equally common, keep values with a 0 + Keep only values with this bit in this position + """ + report = inputs.copy() + for column in range(len(report[0])): + most_common = self.commonality(report) + for binary in list(report): + if (int(binary[column]) == most_common[column]) or (most_common[column] == 2 and binary[column] != "0"): + report.remove(binary) + + if len(report) == 1: + return int(report[0], 2) + + if len(report) > 1: # May not be necessary + report = self.calculate_oxygen_generator_rating(report) + + return int(report[0], 2) + + + def calculate_life_support_rating(self) -> int: + oxygen_generator_rating = self.calculate_oxygen_generator_rating(self.report) + co2_scrubber_rating = self.calculate_co2_scrubber_rating(self.report) + return oxygen_generator_rating * co2_scrubber_rating + + @staticmethod + def commonality(report: List[int]) -> List[Dict[str, int]]: + common_counts = [] + for binary in report: + for column, bit in enumerate(binary): + try: + common_counts[column][bit] += 1 + except IndexError: + common_counts.append(defaultdict(int)) + common_counts[column][bit] = 1 + common = [] + half_total = len(report)/2 + for count in common_counts: + if count["1"] == half_total: + common.append(2) # Indicating equally common + elif count["1"] > half_total: + common.append(1) + else: + common.append(0) + + return common + def part1(inputs: List[int]) -> int: - sub = Submarine() - sub.decode_report(inputs) - return sub.power + diag = Diagnostics(inputs) + return diag.power_usage() def part2(inputs: List[int]) -> int: - return False + diag = Diagnostics(inputs) + return diag.calculate_life_support_rating() def parse(inputs: str) -> List[int]: diff --git a/puzzles/test_day03.py b/puzzles/test_day03.py index 8e2e458..de6fa30 100644 --- a/puzzles/test_day03.py +++ b/puzzles/test_day03.py @@ -23,16 +23,13 @@ def test_example1(example_data): assert aoc.part1(example_data) == 198 -@pytest.mark.skip(reason="Not implemented") def test_example2(example_data): - assert aoc.part2(example_data) == ... + assert aoc.part2(example_data) == 230 -@pytest.mark.skip(reason="Not implemented") -def test_part1(day02_data): - assert aoc.part1(day02_data) == ... +def test_part1(day03_data): + assert aoc.part1(day03_data) == 3885894 -@pytest.mark.skip(reason="Not implemented") -def test_part2(day02_data): - assert aoc.part2(day02_data) == ... +def test_part2(day03_data): + assert aoc.part2(day03_data) == 4375225