Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class Packet:
- def pprint(self, indent=0):
- print(indent*' ' + f'version={self.version}, type_id={self.type_id}, content={self.content}')
- if self.type_id == 4:
- return
- for packet in self.content:
- packet.pprint(indent=indent+4)
- def __init__(self, version, type_id, content):
- self.version = version
- self.type_id = type_id
- self.content = content
- def sum_version(self):
- if not isinstance(self.content, list):
- return self.version
- s = 0
- for content in self.content:
- if isinstance(content, self.__class__):
- s += content.sum_version()
- return self.version + s
- def evaluate_packet(self):
- if self.type_id == 4:
- return self.content
- if self.type_id == 0:
- return sum([packet.evaluate_packet() for packet in self.content])
- if self.type_id == 1:
- return reduce(lambda x, y: x * y, [packet.evaluate_packet() for packet in self.content])
- if self.type_id == 2:
- return min([packet.evaluate_packet() for packet in self.content])
- if self.type_id == 3:
- return max([packet.evaluate_packet() for packet in self.content])
- if self.type_id == 5:
- return 1 if self.content[0].evaluate_packet() > self.content[1].evaluate_packet() else 0
- if self.type_id == 6:
- return 1 if self.content[0].evaluate_packet() < self.content[1].evaluate_packet() else 0
- if self.type_id == 7:
- return 1 if self.content[0].evaluate_packet() == self.content[1].evaluate_packet() else 0
- class PacketDecoder:
- @staticmethod
- def decode(stream):
- if not stream or set(stream) == set('0'):
- return []
- version = int(stream[:3], 2)
- type_id = int(stream[3:6], 2)
- content = []
- if type_id == 4:
- return PacketDecoder.decode_literal_packet(version, type_id, stream)
- return PacketDecoder.decode_operator_packet(version, type_id, stream)
- @staticmethod
- def decode_literal_packet(version, type_id, stream):
- curr_idx = 6
- bin_num = ''
- ended = False
- while not ended:
- if stream[curr_idx] == '0':
- ended=True
- bin_num += stream[curr_idx+1:curr_idx+5]
- curr_idx += 5
- if curr_idx == len(stream) - 1:
- return []
- return [Packet(version, type_id, int(bin_num, 2)), *PacketDecoder.decode(stream[curr_idx:])]
- @staticmethod
- def decode_operator_packet(version, type_id, stream):
- if stream[6] == '0':
- subpacket_stream_len = int(stream[7:7+15], 2)
- subpacket_data = stream[7+15:7+15+subpacket_stream_len]
- return [Packet(version, type_id, PacketDecoder.decode(subpacket_data)), *PacketDecoder.decode(stream[7+15+subpacket_stream_len:])]
- else:
- subpacket_amount = int(stream[7:7+11], 2)
- subdata = PacketDecoder.decode(stream[7+11:])
- return [Packet(version, type_id, subdata[:subpacket_amount]), *subdata[subpacket_amount:]]
- def p1(stream):
- agg_version_sum = 0
- packets = PacketDecoder.decode(stream)
- for packet in packets:
- agg_version_sum += packet.sum_version()
- return agg_version_sum
- def p2(stream):
- return PacketDecoder.decode(stream)[0].evaluate_packet()
- stream = read('sample.txt')
- print(p1(stream))
- print(p2(stream))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement