parent
adf56490c9
commit
76ed46fe11
2 changed files with 127 additions and 0 deletions
@ -0,0 +1,126 @@ |
|||||||
|
def multiply(arr: list[int]) -> int: |
||||||
|
val = 1 |
||||||
|
for elem in arr: |
||||||
|
val *= elem |
||||||
|
return val |
||||||
|
|
||||||
|
|
||||||
|
hexToBinMap = { |
||||||
|
"0": "0000", |
||||||
|
"1": "0001", |
||||||
|
"2": "0010", |
||||||
|
"3": "0011", |
||||||
|
"4": "0100", |
||||||
|
"5": "0101", |
||||||
|
"6": "0110", |
||||||
|
"7": "0111", |
||||||
|
"8": "1000", |
||||||
|
"9": "1001", |
||||||
|
"A": "1010", |
||||||
|
"B": "1011", |
||||||
|
"C": "1100", |
||||||
|
"D": "1101", |
||||||
|
"E": "1110", |
||||||
|
"F": "1111" |
||||||
|
} |
||||||
|
typeIdToOperationMap = { |
||||||
|
0: lambda values: sum(values), |
||||||
|
1: lambda values: multiply(values), |
||||||
|
2: lambda values: min(values), |
||||||
|
3: lambda values: max(values), |
||||||
|
5: lambda values: 1 if values[0] > values[1] else 0, |
||||||
|
6: lambda values: 1 if values[0] < values[1] else 0, |
||||||
|
7: lambda values: 1 if values[0] == values[1] else 0 |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
def readInput(name): |
||||||
|
with open(name) as file: |
||||||
|
binary = "" |
||||||
|
for char in file.read().removesuffix("\n"): |
||||||
|
binary += hexToBinMap[char] |
||||||
|
return binary |
||||||
|
|
||||||
|
|
||||||
|
class Packet: |
||||||
|
|
||||||
|
def __init__(self, version: int): |
||||||
|
self.version = version |
||||||
|
self.bitLength = 6 |
||||||
|
|
||||||
|
def getVersionSum(self) -> int: |
||||||
|
return self.version |
||||||
|
|
||||||
|
def calculate(self) -> int: |
||||||
|
pass |
||||||
|
|
||||||
|
|
||||||
|
class LiteralValue(Packet): |
||||||
|
|
||||||
|
def __init__(self, version: int, content: str): |
||||||
|
super().__init__(version) |
||||||
|
self.value = None |
||||||
|
self.parse(content) |
||||||
|
|
||||||
|
def parse(self, content: str): |
||||||
|
groups = [] |
||||||
|
label = "1" |
||||||
|
while label == "1": |
||||||
|
i = len(groups) * 5 |
||||||
|
label = content[i] |
||||||
|
groups.append(content[i+1:i+5]) |
||||||
|
self.value = int("".join(groups), 2) |
||||||
|
self.bitLength += len(groups) * 5 |
||||||
|
|
||||||
|
def calculate(self) -> int: |
||||||
|
return self.value |
||||||
|
|
||||||
|
|
||||||
|
class Operator(Packet): |
||||||
|
|
||||||
|
def __init__(self, version: int, content: str, typeId: int): |
||||||
|
super().__init__(version) |
||||||
|
self.typeId = typeId |
||||||
|
self.subPackets: list[Packet] = [] |
||||||
|
self.parse(content) |
||||||
|
|
||||||
|
def getVersionSum(self): |
||||||
|
return super().getVersionSum() + sum([p.getVersionSum() for p in self.subPackets]) |
||||||
|
|
||||||
|
def parse(self, content: str): |
||||||
|
lengthTypeId = int(content[0]) |
||||||
|
self.bitLength += 1 |
||||||
|
if lengthTypeId == 0: |
||||||
|
self.bitLength += 15 |
||||||
|
subPacketBitLength = int(content[1:16], 2) |
||||||
|
self.parseSubPackets(content[16:16 + subPacketBitLength]) |
||||||
|
if lengthTypeId == 1: |
||||||
|
self.bitLength += 11 |
||||||
|
subPacketCount = int(content[1:12], 2) |
||||||
|
self.parseSubPackets(content[12:], subPacketCount) |
||||||
|
|
||||||
|
def parseSubPackets(self, content: str, subPacketCount: int = None): |
||||||
|
pos = 0 |
||||||
|
while pos < len(content) and (subPacketCount is None or len(self.subPackets) < subPacketCount): |
||||||
|
packet = parsePacket(content[pos:]) |
||||||
|
pos += packet.bitLength |
||||||
|
self.subPackets.append(packet) |
||||||
|
self.bitLength += pos |
||||||
|
|
||||||
|
def calculate(self) -> int: |
||||||
|
subResults = [p.calculate() for p in self.subPackets] |
||||||
|
return typeIdToOperationMap[self.typeId](subResults) |
||||||
|
|
||||||
|
|
||||||
|
def parsePacket(binary: str): |
||||||
|
version = int(binary[:3], 2) |
||||||
|
typeId = int(binary[3:6], 2) |
||||||
|
if typeId == 4: |
||||||
|
return LiteralValue(version, binary[6:]) |
||||||
|
else: |
||||||
|
return Operator(version, binary[6:], typeId) |
||||||
|
|
||||||
|
|
||||||
|
mainPacket = parsePacket(readInput("input")) |
||||||
|
print(mainPacket.getVersionSum()) |
||||||
|
print(mainPacket.calculate()) |
@ -0,0 +1 @@ |
|||||||
|
9C0141080250320F1802104A08 |
Loading…
Reference in new issue