summaryrefslogtreecommitdiffstats
path: root/3.py
diff options
context:
space:
mode:
authorTomasz Kramkowski <tk@the-tk.com>2021-12-03 09:05:58 +0000
committerTomasz Kramkowski <tk@the-tk.com>2021-12-03 09:05:58 +0000
commitc45449b1a1cd0eee0c481e1a4f784686e44bb49d (patch)
tree6e27d657a6f0adb647bc4a5855c62ae5dbe00482 /3.py
parent72724bb3a507465b8f1df65eeb6a3bee62549705 (diff)
downloadaoc2021-c45449b1a1cd0eee0c481e1a4f784686e44bb49d.tar.gz
aoc2021-c45449b1a1cd0eee0c481e1a4f784686e44bb49d.tar.xz
aoc2021-c45449b1a1cd0eee0c481e1a4f784686e44bb49d.zip
day 3
Diffstat (limited to '3.py')
-rw-r--r--3.py48
1 files changed, 48 insertions, 0 deletions
diff --git a/3.py b/3.py
new file mode 100644
index 0000000..32596ef
--- /dev/null
+++ b/3.py
@@ -0,0 +1,48 @@
+from typing import Generator
+from collections.abc import Iterable
+from collections import Counter
+
+Bits = tuple[bool, ...]
+Input = list[Bits]
+
+def column(rows: Iterable[Bits], n: int) -> Generator[bool, None, None]:
+ for row in rows:
+ yield row[n]
+
+def most_common(bits: Iterable[bool]) -> bool:
+ freqs: list[tuple[bool, int]] = Counter(bits).most_common()
+ if freqs[0][1] == freqs[1][1]:
+ return True
+ return freqs[0][0]
+
+def bits_to_int(bits: Bits) -> int:
+ ret: int = 0
+ for i, b in enumerate(reversed(bits)):
+ if b:
+ ret += 2 ** i
+ return ret
+
+def part1(nums: Input) -> int:
+ nbits: int = len(nums[0])
+ gamma: Bits = tuple(most_common(column(inp, i)) for i in range(nbits))
+ epsilon: Bits = tuple(not bit for bit in gamma)
+ return bits_to_int(gamma) * bits_to_int(epsilon)
+
+def part2_impl(nums: Input, complement: bool, bit: int = 0) -> Bits:
+ if len(nums) == 1:
+ return nums[0]
+ target: bool = most_common(column(nums, bit))
+ if complement:
+ target = not target
+ nums = list(filter(lambda n: n[bit] == target, nums))
+ return part2_impl(nums, complement, bit + 1)
+
+def part2(nums: Input) -> int:
+ oxygen: Bits = part2_impl(nums, False)
+ co2: Bits = part2_impl(nums, True)
+ return bits_to_int(oxygen) * bits_to_int(co2)
+
+inp: Input = [tuple(bool(int(c)) for c in l.strip()) for l in open('3.in')]
+
+print(part1(inp))
+print(part2(inp))