aboutsummaryrefslogtreecommitdiff
path: root/2021/16/puzzles.py
diff options
context:
space:
mode:
authorThomas Voss <thomasvoss@live.com> 2021-12-16 12:08:07 +0100
committerThomas Voss <thomasvoss@live.com> 2021-12-16 12:08:07 +0100
commit8fd28be759da93efc80abd230fb33a045ed366c9 (patch)
treea670ebc898be170686c01dda24407fd8789df062 /2021/16/puzzles.py
parentf05d35537b96c9f0595caa7ef09bc8802bacfc43 (diff)
Add day 16 solutions
Diffstat (limited to '2021/16/puzzles.py')
-rw-r--r--2021/16/puzzles.py90
1 files changed, 90 insertions, 0 deletions
diff --git a/2021/16/puzzles.py b/2021/16/puzzles.py
new file mode 100644
index 0000000..75e29d1
--- /dev/null
+++ b/2021/16/puzzles.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python3
+
+from math import prod
+from typing import NamedTuple
+
+data: str
+
+
+class Packet(NamedTuple):
+ pass
+
+
+class Packet(NamedTuple):
+ version: int
+ type: int
+ value: int
+ subpackets: list[Packet]
+
+ def calculate(self) -> int:
+ f = lambda p: p.calculate()
+
+ # START PART 1
+ return self.version + sum(map(f, self.subpackets))
+ # END PART 1 START PART 2
+ match self.type:
+ case 0:
+ return sum(map(f, self.subpackets))
+ case 1:
+ return prod(map(f, self.subpackets))
+ case 2:
+ return min(map(f, self.subpackets))
+ case 3:
+ return max(map(f, self.subpackets))
+ case 4:
+ return self.value
+ case 5:
+ return self.subpackets[0].calculate() > self.subpackets[1].calculate()
+ case 6:
+ return self.subpackets[0].calculate() < self.subpackets[1].calculate()
+ case 7:
+ return self.subpackets[0].calculate() == self.subpackets[1].calculate()
+ # END PART 2
+
+
+def solve() -> Packet:
+ global data
+
+ v = int(data[:3], 2)
+ t = int(data[3:6], 2)
+ data = data[6:]
+
+ if t == 4:
+ val = ""
+ while data[0] == "1":
+ val += data[1:5]
+ data = data[5:]
+ val += data[1:5]
+ data = data[5:]
+ return Packet(v, t, int(val, 2), [])
+
+ l = data[0]
+ data = data[1:]
+
+ if l == "0":
+ length = int(data[:15], 2)
+ data = data[15:]
+ oldlen = len(data)
+
+ subpackets = []
+ while oldlen - len(data) < length:
+ subpackets.append(solve())
+
+ return Packet(v, t, 0, subpackets)
+
+ n = int(data[:11], 2)
+ data = data[11:]
+ return Packet(v, t, 0, [solve() for _ in range(n)])
+
+
+def main() -> None:
+ global data
+
+ with open("input", "r", encoding="utf-8") as f:
+ data = "".join(bin(n)[2:].zfill(8) for n in bytes.fromhex(f.read().strip()))
+
+ print(solve().calculate())
+
+
+if __name__ == "__main__":
+ main()