day16: muuuuch nicer code
This commit is contained in:
parent
1339bd60f7
commit
23f9d800f8
136
day16.py
136
day16.py
@ -1,100 +1,64 @@
|
|||||||
from math import prod
|
from math import prod
|
||||||
|
|
||||||
from tools.aoc import AOCDay
|
from tools.aoc import AOCDay
|
||||||
from typing import Any, List
|
from typing import Any, List
|
||||||
|
|
||||||
|
|
||||||
def get_packet(bit_rep: str) -> (str, int): # packet, packet_length
|
class Packet:
|
||||||
msg_type = int(bit_rep[3:6], 2)
|
def __init__(self, packet_str: str):
|
||||||
index = 6
|
self.packet_str = packet_str
|
||||||
|
self.p_version = int(packet_str[:3], 2)
|
||||||
|
self.p_type = int(packet_str[3:6], 2)
|
||||||
|
self.p_len = 6
|
||||||
|
self.value = 0
|
||||||
|
self.sub_packets = []
|
||||||
|
self.__parse()
|
||||||
|
|
||||||
if msg_type == 4:
|
def __parse(self):
|
||||||
while bit_rep[index] == "1":
|
if self.p_type == 4:
|
||||||
index += 5
|
while self.packet_str[self.p_len] == "1":
|
||||||
index += 5
|
self.value = self.value * 16 + int(self.packet_str[self.p_len + 1:self.p_len + 5], 2)
|
||||||
|
self.p_len += 5
|
||||||
|
self.value = self.value * 16 + int(self.packet_str[self.p_len + 1:self.p_len + 5], 2)
|
||||||
|
self.p_len += 5
|
||||||
else:
|
else:
|
||||||
op_type = bit_rep[index]
|
op_type = self.packet_str[self.p_len]
|
||||||
index += 1
|
self.p_len += 1
|
||||||
if op_type == "0":
|
if op_type == "0":
|
||||||
sub_pkg_len = int(bit_rep[index:index+15], 2)
|
sub_pkg_len = int(self.packet_str[self.p_len:self.p_len + 15], 2)
|
||||||
index += 15 + sub_pkg_len
|
self.p_len += 15 + sub_pkg_len
|
||||||
else:
|
sub_packages = self.packet_str[self.p_len - sub_pkg_len:self.p_len]
|
||||||
sub_pkg_count = int(bit_rep[index:index+11], 2)
|
|
||||||
index += 11
|
|
||||||
for x in range(sub_pkg_count):
|
|
||||||
_, sub_pkg_len = get_packet(bit_rep[index:])
|
|
||||||
index += sub_pkg_len
|
|
||||||
|
|
||||||
return bit_rep[:index], index
|
|
||||||
|
|
||||||
|
|
||||||
def get_subpackages(packet: str) -> List[str]:
|
|
||||||
ptype = int(packet[3:6], 2)
|
|
||||||
if ptype == 4:
|
|
||||||
return [packet]
|
|
||||||
else:
|
|
||||||
plist = []
|
|
||||||
op_type = packet[6]
|
|
||||||
if op_type == "0":
|
|
||||||
sub_pkg_len = int(packet[7:22], 2)
|
|
||||||
sub_packages = packet[22:22+sub_pkg_len]
|
|
||||||
while "1" in sub_packages:
|
while "1" in sub_packages:
|
||||||
sub_packet, sub_pkg_len = get_packet(sub_packages)
|
sub_packet = Packet(sub_packages)
|
||||||
sub_packages = sub_packages[sub_pkg_len:]
|
self.sub_packets.append(sub_packet)
|
||||||
plist.append(sub_packet)
|
sub_packages = sub_packages[sub_packet.p_len:]
|
||||||
else:
|
else:
|
||||||
sub_pkg_count = int(packet[7:18], 2)
|
sub_pkg_count = int(self.packet_str[self.p_len:self.p_len + 11], 2)
|
||||||
index = 18
|
self.p_len += 11
|
||||||
for x in range(sub_pkg_count):
|
for x in range(sub_pkg_count):
|
||||||
sub_packet, sub_pkg_len = get_packet(packet[index:])
|
sub_packet = Packet(self.packet_str[self.p_len:])
|
||||||
index += sub_pkg_len
|
self.sub_packets.append(sub_packet)
|
||||||
plist.append(sub_packet)
|
self.p_len += sub_packet.p_len
|
||||||
|
|
||||||
return plist
|
def get_versions(self) -> int:
|
||||||
|
return self.p_version + sum(p.get_versions() for p in self.sub_packets)
|
||||||
|
|
||||||
|
def get_value(self) -> int:
|
||||||
def get_versions(packet: str) -> int:
|
if self.p_type == 0:
|
||||||
version = int(packet[0:3], 2)
|
return sum(p.get_value() for p in self.sub_packets)
|
||||||
ptype = int(packet[3:6], 2)
|
elif self.p_type == 1:
|
||||||
if ptype == 4:
|
return prod(p.get_value() for p in self.sub_packets)
|
||||||
return version
|
elif self.p_type == 2:
|
||||||
else:
|
return min(p.get_value() for p in self.sub_packets)
|
||||||
for p in get_subpackages(packet):
|
elif self.p_type == 3:
|
||||||
version += get_versions(p)
|
return max(p.get_value() for p in self.sub_packets)
|
||||||
|
elif self.p_type == 4:
|
||||||
return version
|
return self.value
|
||||||
|
elif self.p_type == 5:
|
||||||
|
return self.sub_packets[0].get_value() > self.sub_packets[1].get_value()
|
||||||
def get_value(packet: str) -> int:
|
elif self.p_type == 6:
|
||||||
while "1" in packet:
|
return self.sub_packets[0].get_value() < self.sub_packets[1].get_value()
|
||||||
this_packet, pkg_len = get_packet(packet)
|
elif self.p_type == 7:
|
||||||
pkg_type = int(this_packet[3:6], 2)
|
return self.sub_packets[0].get_value() == self.sub_packets[1].get_value()
|
||||||
packet = packet[pkg_len:]
|
|
||||||
if pkg_type == 0:
|
|
||||||
return sum(get_value(p) for p in get_subpackages(this_packet))
|
|
||||||
elif pkg_type == 1:
|
|
||||||
return prod(get_value(p) for p in get_subpackages(this_packet))
|
|
||||||
elif pkg_type == 2:
|
|
||||||
return min(get_value(p) for p in get_subpackages(this_packet))
|
|
||||||
elif pkg_type == 3:
|
|
||||||
return max(get_value(p) for p in get_subpackages(this_packet))
|
|
||||||
elif pkg_type == 4:
|
|
||||||
index = 6
|
|
||||||
value = 0
|
|
||||||
while this_packet[index] == "1":
|
|
||||||
value = value * 16 + int(this_packet[index + 1:index + 5], 2)
|
|
||||||
index += 5
|
|
||||||
value = value * 16 + int(this_packet[index + 1:index + 5], 2)
|
|
||||||
return value
|
|
||||||
elif pkg_type == 5:
|
|
||||||
sub_pkg = get_subpackages(this_packet)
|
|
||||||
return get_value(sub_pkg[0]) > get_value(sub_pkg[1])
|
|
||||||
elif pkg_type == 6:
|
|
||||||
sub_pkg = get_subpackages(this_packet)
|
|
||||||
return get_value(sub_pkg[0]) < get_value(sub_pkg[1])
|
|
||||||
elif pkg_type == 7:
|
|
||||||
sub_pkg = get_subpackages(this_packet)
|
|
||||||
return get_value(sub_pkg[0]) == get_value(sub_pkg[1])
|
|
||||||
|
|
||||||
|
|
||||||
class Day(AOCDay):
|
class Day(AOCDay):
|
||||||
@ -106,7 +70,7 @@ class Day(AOCDay):
|
|||||||
return "0" * (len(self.getInput()) * 4 - len(bits)) + bits
|
return "0" * (len(self.getInput()) * 4 - len(bits)) + bits
|
||||||
|
|
||||||
def part1(self) -> Any:
|
def part1(self) -> Any:
|
||||||
return get_versions(self.getBits())
|
return Packet(self.getBits()).get_versions()
|
||||||
|
|
||||||
def part2(self) -> Any:
|
def part2(self) -> Any:
|
||||||
return get_value(self.getBits())
|
return Packet(self.getBits()).get_value()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user