diff options
Diffstat (limited to 'day3/__init__.py')
| -rw-r--r-- | day3/__init__.py | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/day3/__init__.py b/day3/__init__.py new file mode 100644 index 0000000..29f4ab3 --- /dev/null +++ b/day3/__init__.py | |||
| @@ -0,0 +1,96 @@ | |||
| 1 | from collections import Counter | ||
| 2 | from copy import copy | ||
| 3 | from dataclasses import dataclass | ||
| 4 | from typing import Iterator, List | ||
| 5 | |||
| 6 | from aoc import BaseAssignment | ||
| 7 | |||
| 8 | class Assignment(BaseAssignment): | ||
| 9 | def read_input(self, example = False) -> List[str]: | ||
| 10 | return list(super().read_input(example)) | ||
| 11 | |||
| 12 | @staticmethod | ||
| 13 | def flip(bits: str) -> str: | ||
| 14 | return bin(~int(bits, 2) + (1 << len(bits))).strip('0b') | ||
| 15 | |||
| 16 | |||
| 17 | class AssignmentOne(Assignment): | ||
| 18 | example_result = 198 | ||
| 19 | @staticmethod | ||
| 20 | def convert(input: List[str]) -> List[List[str]]: | ||
| 21 | items = [] | ||
| 22 | for item in input: | ||
| 23 | for index, char in enumerate([char for char in item]): | ||
| 24 | try: | ||
| 25 | items[index].append(char) | ||
| 26 | except IndexError: | ||
| 27 | items.append([char]) | ||
| 28 | |||
| 29 | return items | ||
| 30 | |||
| 31 | @staticmethod | ||
| 32 | def gamma_rate(input: List[str]) -> str: | ||
| 33 | converted = AssignmentOne.convert(input) | ||
| 34 | return ''.join([ | ||
| 35 | Counter(i).most_common(1)[0][0] | ||
| 36 | for i | ||
| 37 | in converted | ||
| 38 | ]) | ||
| 39 | |||
| 40 | @staticmethod | ||
| 41 | def epsilon_rate(input: List[str]) -> str: | ||
| 42 | return Assignment.flip(AssignmentOne.gamma_rate(input)) | ||
| 43 | |||
| 44 | def run(self, input: List[str]) -> int: | ||
| 45 | return int(self.gamma_rate(input), 2) * int(self.epsilon_rate(input), 2) | ||
| 46 | |||
| 47 | |||
| 48 | class AssignmentTwo(Assignment): | ||
| 49 | example_result = 230 | ||
| 50 | |||
| 51 | @staticmethod | ||
| 52 | def oxygen_generator_rating(input: List[str]): | ||
| 53 | bit_length = len(input[0]) | ||
| 54 | |||
| 55 | modified_input = copy(input) | ||
| 56 | bits = '' | ||
| 57 | for i in range(bit_length): | ||
| 58 | count = Counter([_[i] for _ in modified_input]).most_common(2) | ||
| 59 | |||
| 60 | most_used = count[0] | ||
| 61 | most_used_count = most_used[1] | ||
| 62 | least_used = count[-1] | ||
| 63 | least_used_count = least_used[1] | ||
| 64 | |||
| 65 | bit = '1' if most_used_count == least_used_count else most_used[0] | ||
| 66 | |||
| 67 | bits += bit | ||
| 68 | modified_input = list(filter(lambda _: _[i] == bit, modified_input)) | ||
| 69 | |||
| 70 | return bits | ||
| 71 | |||
| 72 | @staticmethod | ||
| 73 | def co2_scrubbing_rating(input: List[str]): | ||
| 74 | bit_length = len(input[0]) | ||
| 75 | |||
| 76 | modified_input = copy(input) | ||
| 77 | for i in range(bit_length): | ||
| 78 | if len(modified_input) == 1: | ||
| 79 | return modified_input[0] | ||
| 80 | |||
| 81 | count = Counter([_[i] for _ in modified_input]).most_common(2) | ||
| 82 | |||
| 83 | most_used = count[0] | ||
| 84 | most_used_count = most_used[1] | ||
| 85 | least_used = count[-1] | ||
| 86 | least_used_count = least_used[1] | ||
| 87 | |||
| 88 | bit = '0' if most_used_count == least_used_count else least_used[0] | ||
| 89 | |||
| 90 | modified_input = list(filter(lambda _: _[i] == bit, modified_input)) | ||
| 91 | |||
| 92 | |||
| 93 | def run(self, input: List[str]) -> int: | ||
| 94 | return int(AssignmentTwo.oxygen_generator_rating(input), 2) \ | ||
| 95 | * int(AssignmentTwo.co2_scrubbing_rating(input), 2) | ||
| 96 | |||
