Dazbo's Advent of Code solutions, written in Python
binary and hexadecimalString format
Urgh. This one was brutal. Up until this challenge, all the solutions here took me under two hours. This one took me half a day.
It’s not that hard. But it takes quite a bit of time to fully understand the instructions, and it’s really easy to make mistakes. Fortunately, the problem does come with a lot of examples to work through, which I found to be essential in debugging my solution. I’d also recommend generous use of debug statements as you work your way through!
So, we’re told that we’ve received a transmission in a proprietary BITS format, which is received as a stream of hexadecimal values.
The transmission contains a single outer packet, which in turn contains multiple adjacent inner packets. Each of these inner packets can contain yet more inner packets, and so on.
Although the actual input will only be a single hex stream on a single line, we’ve been given quite a few samples to work through. So, my sample data includes a bunch of these samples:
C200B40A82
04005AC33890
880086C3E88112
CE00C43D881120
D8005AC2A8F0
F600BC2D8F
9C005AC2F8F0
9C0141080250320F1802104A08
A0016C880162017C3686B18A3D4780
We’re told an individual packet has a structure like this:
vvv ttt [n*p][x*0]
where:
v
= 3 bit packet versiont
= 3 bit packet type IDp
= a number of bits for a literal value (l
) or an operator packet (o
)x
= a number of 0s, to pad out the remaining bits such that the overall length is a multiple of 4 (since the original stream came from a number of hex digits)If a literal packet:
If an operator packet:
length type ID
which is one of two types:
0
, then the next 15 bits indiate the overal length of all the subpackets in this operator.1
, then the next 11 bits represent the number of subpackets immediately contained in this operator packet.We’re asked to find the sum of all the version numbers in the input data. Since packets can contain other packets, this lends itself to a recursive solution. Each packet will either contain other packets, or itself be a leaf node.
Before we crack on with the code, let’s just break down one of the examples:
A 0 0 1 6 C 8 8 0 1 6 2 0 1 7 C 3 6 8 6 B 1 8 A 3 D 4 7 8 0 (HEX) 1010 0000 0000 0001 0110 1100 1000 1000 0000 0001 0110 0010 0000 0001 0111 1100 0011 0110 1000 0110 1011 0001 1000 1010 0011 1101 0100 0111 1000 0000 (BIN)101 000 000000000101101100100010000000000101100010000000010111110000110110100001101011000110001010001111010100011110000000 (Lvl 0)V=5 Version=5 5 T=0 Type=Operator 0 Len ID=0 , so 15-bit repr of number of bits in subpackets000000001011011 Sub-packets are 91 bits in total 001 000 1000000000010110001000000001011111000011011010000110101100011000101000111101010001111 (Lvl 1)V=1 1 T=0 1 Len ID=1 , so 11-bit repr of subpackets00000000001 1 sub-packet 011 000 1000000001011111000011011010000110101100011000101000111101010001111 (Lvl 2)V=3 3 T=0 1 Len ID=1 , so 11-bit repr of subpackets00000000101 so 5 subpackets 111 100 00110110 100 00110101 100 01100010 100 01111010 100 01111 (Lvl 3)V=7 V=6 V=5 V=2 V=2 22 T=4 T=4 T=4 T=4 T=4 00110 00110 01100 01111 01111TOTAL: 31
So this is the design of my solution:
Packet
holds a list
of subpackets. Track the depth of subpackets.Let’s start by reading in the data:
input_file = os.path.join(SCRIPT_DIR, INPUT_FILE)
with open(input_file, mode="rt") as f:
# Each line has a single outer packet. Actual input is only one line, but our test data has many lines.
outer_packets_data = [hex_to_bin(line) for line in f.read().splitlines()]
for outer_packet_data in outer_packets_data:
packet = Packet(outer_packet_data)
logger.info(packet)
def hex_to_bin(hex_value) -> str:
""" Convert all hex digits to binary representation, with leading zeroes """
bin_len = 4*len(hex_value) # 4 bits per hex
return "{0:0{width}b}".format(int(hex_value, 16), width=bin_len)
We:
list
of outer_packets_data
, by reading each line of input, and converting each line from hex to binary.hex_to_bin()
method converts all the hex digits to binary digits.
int(value, base)
, where base=16
.format spec
, where:
{0}
is the first parameter to the format()
method, i.e. the decimal value;:0{width}b
tells format()
to convert to binary
type, and then pad with 0
in order to achieve the desired str
length.list
is an outer packet, so we construct a Packet
from each item.Now let’s look at the Packet
class itself:
class Packet():
""" Processes a BITS packet, including recursive processing of any inner packets. """
VER_START = 0
TYPE_START = 3
VAL_START = 6
def __init__(self, bin_input_stream: str, level=0) -> None:
""" Creates a packet instance. Expects the input as str of bits.
Nesting level defaults to 0. Sub-packets have level incremented automatically. """
self._bin_in_str = bin_input_stream # The raw binary data given to the class
self._processed_bin_digits = 0 # Increment this throughout stages
self._level = level # Nesting level. Starts at level 0
logger.debug("Lvl=%s: raw bin=%s", self._level, self._bin_in_str)
self._literal_val = 0
self._sub_packets: list[Packet] = [] # any nested packets
self._version = int(self._bin_in_str[Packet.VER_START:Packet.TYPE_START], 2)
self._processed_bin_digits += Packet.TYPE_START
self._process_type() # evaluate if literal or operation type and process accordingly
self._bin_in_self = bin_input_stream[0:self._processed_bin_digits] # All the bits that represent this packet
self._remaining_from_stream = bin_input_stream[self._processed_bin_digits:] # Bits we haven't yet consumed from input
def __len__(self):
""" The length of this packet (including subpackets), but excluding extraneous data from the input stream """
return len(self._bin_in_self)
@property
def version_sum(self) -> int:
""" The sum of the version of this packet, as well as the versions of all subpackets. """
return self._version + sum(sub_packet.version_sum for sub_packet in self._sub_packets)
@property
def value(self) -> int:
""" Determine value for this type of packet, recursively. """
return self._literal_val
@property
def remaining_from_stream(self):
""" Returns unconsumed BINARY digits. """
return self._remaining_from_stream
def _process_type(self):
""" Determine whether literal (type 4) or operator (type other) packet """
self._type = int(self._bin_in_str[Packet.TYPE_START:Packet.VAL_START], 2)
self._processed_bin_digits += Packet.VAL_START - Packet.TYPE_START
if self._type == 4: # literal
self._literal_val = self._process_literal()
else: # operator
self._process_operator()
def _process_literal(self):
""" [5*l] where each block of 5 bits starts with a 1, except the last. """
grp_len = 5
# grab groups one at a time, until we grab the one starting with a 0
groups_start = Packet.VAL_START
grps = ""
while True:
group = self._bin_in_str[groups_start:groups_start + grp_len]
grps += group[1:] # Not interested in first digit of each group
self._processed_bin_digits += grp_len
if group[0] == '0': # this is the last group
break
groups_start += grp_len
self._literal_bin = grps
return int(self._literal_bin, 2)
def _process_operator(self):
""" If m=0, next 15 bits are total length of subpackets: [m[bbbbbbbbbbbbbbb]s*[]]
If m=1, next 11 bits are the number of subsequent subpackets """
SUBPACKETS_LEN_FIELD_SZ = 15
SUBPACKETS_CONTAINED_FIELD_SZ = 11
len_type_id = int(self._bin_in_str[Packet.VAL_START])
self._processed_bin_digits += 1
if len_type_id == 0:
# Next 15 bits is number that represents total length (in bits) of subpackets
sub_packets_start = Packet.VAL_START+1+SUBPACKETS_LEN_FIELD_SZ
self._processed_bin_digits += SUBPACKETS_LEN_FIELD_SZ
sub_packets_total_len = int(self._bin_in_str[Packet.VAL_START+1: sub_packets_start], 2)
sub_packets_end = sub_packets_start + sub_packets_total_len
# Extract the portion of this packet that contains all the sub_packets
sub_packets_data = self._bin_in_str[sub_packets_start: sub_packets_end]
# Parse these subpackets sequentially, until no more remain
processed_bits = 0
while processed_bits < sub_packets_total_len:
sub_packet = Packet(sub_packets_data, self._level+1)
processed_bits += len(sub_packet)
self._sub_packets.append(sub_packet)
sub_packets_data = sub_packet.remaining_from_stream
self._processed_bin_digits += sub_packets_total_len
else:
# Next 11 bits are mumber that represents number of sub-packets contained
assert len_type_id == 1, "Len_type must be 0 or 1"
self._processed_bin_digits += SUBPACKETS_CONTAINED_FIELD_SZ
sub_packets_start = Packet.VAL_START+1+SUBPACKETS_CONTAINED_FIELD_SZ
num_subpackets = int(self._bin_in_str[Packet.VAL_START+1: sub_packets_start], 2)
sub_packets_data = self._bin_in_str[sub_packets_start:]
# Parse these n subpackets sequentially, until no more remain
processed_bits = 0
while len(self._sub_packets) < num_subpackets:
sub_packet = Packet(sub_packets_data, self._level+1)
processed_bits += len(sub_packet)
self._sub_packets.append(sub_packet)
sub_packets_data = sub_packet.remaining_from_stream
self._processed_bin_digits += processed_bits
def __str__(self) -> str:
""" Short representation at top level only """
hex_repr = hex(int(self._bin_in_str, 2)).upper()[2:]
show_len = 10
if len(hex_repr) > show_len:
hex_repr = hex_repr[:show_len] + "..."
return (f"Packet:LVL={self._level},VerSum={self.version_sum},Ver={self._version}," +
f"T={self._type},Val={self.value},hex={hex_repr}")
def __repr__(self) -> str:
""" Show packet information, including recursive detail """
if self._sub_packets:
val = ",".join(repr(sub_packet) for sub_packet in self._sub_packets)
else:
val = self._literal_val
return ("\n" + (" " * self._level)
+ f"[Packet:LVL={self._level},VerSum={self.version_sum},Ver={self._version},T={self._type},value={val}]")
It works like this:
Packet
class has some class constants which are used to determine which bits are used for slicing the data, in order to obtain version, type, and value components of the Packet
.
Each outer Packet
is created from the entire binary line. The outer packets have level
set to the default of 0
._bin_in_str
.Packet
has a variable called _sub_packets
, for storing a list
of subpackets, if there are any._version
. We increment _processed_bin_digits
, i.e. to reflect that we’ve read these 3 bits._process_type()
method, which:
_processed_bin_digits
accordingly._process_literal()
._process_operator()
._process_literal()
method reads the subsequent groups, as required, and updates the Packet's _literal_val
accordingly._process_operator()
method is more complex. This method:
_processed_bin_digits
value.Packet's _bin_in_self
value, such that it is the number of bits that was read to create this packet, including its subpackets.Other methods worth mentioning:
value
property simply returns _literal_val
.version_sum
property is a simple recursive function that returns the current packet’s version
value, add adds the sum of the version
values of any subpackets. Obviously, this function will recurse for as long as there are packets with subpackets.And finally, a note on representing the object:
__str__()
method provides a simple representation of the Packet
object. It only shows the outer packet informatino, i.e.
level
of this packet
, where 0 is for the outermost packets.version
of this packet
.type
of this packet
.value
(i.e. _literal_val
) of this packet
.__repr__()
method, which provides a more detailed recursive view of the Packet
object, and all nested packets.
,
." " * self._level
.To demonstrate these two in action, we’ll test using our A0016C880162017C3686B18A3D4780
sample. First, using __str__()
:
print(packet)
Output:
Packet:LVL=0,VerSum=31,Ver=5,T=0,Val=0,hex=A0016C8801...
And now using __repr__()
:
print(repr(packet))
Output:
[Packet:LVL=0,VerSum=31,Ver=5,T=0,value=
[Packet:LVL=1,VerSum=26,Ver=1,T=0,value=
[Packet:LVL=2,VerSum=25,Ver=3,T=0,value=
[Packet:LVL=3,VerSum=7,Ver=7,T=4,value=6],
[Packet:LVL=3,VerSum=6,Ver=6,T=4,value=6],
[Packet:LVL=3,VerSum=5,Ver=5,T=4,value=12],
[Packet:LVL=3,VerSum=2,Ver=2,T=4,value=15],
[Packet:LVL=3,VerSum=2,Ver=2,T=4,value=15]]]]
Notice how the __repr()__
version mirrors the worked example from above. This version is extremely helpful when debugging!
Now we’re asked to calculate the value of the transmission. This is entirely dependent on the type ID
, and we’re told that each type
requies a different form of processing. I.e.
Type ID | Operation |
---|---|
0 | Sum value of subpackets. If only one sub-packet, then return the value of the subpacket. |
1 | Product of values of subpackets. If only one sub-packet, return the value of the subpacket. |
2 | Minimum of values of all subpackets. |
3 | Maximum of values of all subpackets. |
4 | Return _literal_val |
5 | 1 if first subpacket > than second subpacket, else 0. |
6 | 1 if first subpacket < than second subpacket, else 0. |
7 | 1 if first subpacket == second subpacket, else 0. |
There’s very little we need to do. In fact, the only change required is to the value
property in our Packet
class. The new version still returns self._literal_val
for the _type == 4
case, but otherwise recurses into subpackets, as required for each operation.
@property
def value(self) -> int:
""" Determine value for this type of packet, recursively. """
val = 0
if self._type == 0: # recursive sum of values
for sub_packet in self._sub_packets:
val += sub_packet.value
elif self._type == 1: # recursive product of values
val = 1
for sub_packet in self._sub_packets:
val *= sub_packet.value
elif self._type == 2: # minimum of sub-packets
val = min(sub_packet.value for sub_packet in self._sub_packets)
elif self._type == 3: # maximum of sub-packets
val = max(sub_packet.value for sub_packet in self._sub_packets)
elif self._type == 4: # return the value encoding in the literal (type 4) packet
val = self._literal_val
elif self._type == 5: # 1 if 1st packet > 2nd packet, else 0
val = 1 if self._sub_packets[0].value > self._sub_packets[1].value else 0
elif self._type == 6: # 1 if 1st packet < 2nd packet, else 0
val = 1 if self._sub_packets[0].value < self._sub_packets[1].value else 0
elif self._type == 7: # 1 if 1st packet == 2nd packet, else 0
val = 1 if self._sub_packets[0].value == self._sub_packets[1].value else 0
else:
assert False, "We should never get here!"
return val
So the final output looks something like this:
19:42:00.324:INFO:__main__: Packet:LVL=0,VerSum=977,Ver=1,T=0,Val=101501020883,hex=220D4B8049...
19:42:00.325:INFO:__main__: Execution time: 0.0024 seconds
And, just in case you were wondering what the __repr__()
would look like…
[Packet:LVL=0,VerSum=977,Ver=1,T=0,value=
[Packet:LVL=1,VerSum=24,Ver=1,T=3,value=
[Packet:LVL=2,VerSum=4,Ver=4,T=4,value=15],
[Packet:LVL=2,VerSum=7,Ver=7,T=4,value=199071281],
[Packet:LVL=2,VerSum=7,Ver=7,T=4,value=499],
[Packet:LVL=2,VerSum=5,Ver=5,T=4,value=190]],
[Packet:LVL=1,VerSum=20,Ver=6,T=1,value=
[Packet:LVL=2,VerSum=2,Ver=2,T=4,value=240],
[Packet:LVL=2,VerSum=12,Ver=4,T=5,value=
[Packet:LVL=3,VerSum=7,Ver=7,T=4,value=3410],
[Packet:LVL=3,VerSum=1,Ver=1,T=4,value=201]]],
[Packet:LVL=1,VerSum=8,Ver=7,T=3,value=
[Packet:LVL=2,VerSum=1,Ver=1,T=4,value=7]],
[Packet:LVL=1,VerSum=38,Ver=5,T=1,value=
[Packet:LVL=2,VerSum=4,Ver=4,T=4,value=51786],
[Packet:LVL=2,VerSum=29,Ver=4,T=7,value=
[Packet:LVL=3,VerSum=16,Ver=2,T=0,value=
[Packet:LVL=4,VerSum=5,Ver=5,T=4,value=15],
[Packet:LVL=4,VerSum=3,Ver=3,T=4,value=11],
[Packet:LVL=4,VerSum=6,Ver=6,T=4,value=14]],
[Packet:LVL=3,VerSum=9,Ver=6,T=0,value=
[Packet:LVL=4,VerSum=0,Ver=0,T=4,value=6],
[Packet:LVL=4,VerSum=3,Ver=3,T=4,value=11],
[Packet:LVL=4,VerSum=0,Ver=0,T=4,value=5]]]],
[Packet:LVL=1,VerSum=5,Ver=5,T=4,value=2513],
[Packet:LVL=1,VerSum=27,Ver=7,T=1,value=
[Packet:LVL=2,VerSum=2,Ver=2,T=4,value=28408],
[Packet:LVL=2,VerSum=18,Ver=6,T=5,value=
[Packet:LVL=3,VerSum=5,Ver=5,T=4,value=52653],
[Packet:LVL=3,VerSum=7,Ver=7,T=4,value=52653]]],
[Packet:LVL=1,VerSum=4,Ver=4,T=4,value=751],
[Packet:LVL=1,VerSum=5,Ver=5,T=4,value=936579],
[Packet:LVL=1,VerSum=9,Ver=2,T=1,value=
[Packet:LVL=2,VerSum=5,Ver=5,T=4,value=84],
[Packet:LVL=2,VerSum=2,Ver=0,T=5,value=
[Packet:LVL=3,VerSum=2,Ver=2,T=4,value=246356739],
[Packet:LVL=3,VerSum=0,Ver=0,T=4,value=15228190]]],
[Packet:LVL=1,VerSum=27,Ver=3,T=1,value=
[Packet:LVL=2,VerSum=6,Ver=6,T=4,value=321243],
[Packet:LVL=2,VerSum=18,Ver=7,T=7,value=
[Packet:LVL=3,VerSum=4,Ver=4,T=4,value=212],
[Packet:LVL=3,VerSum=7,Ver=7,T=4,value=631]]],
[Packet:LVL=1,VerSum=16,Ver=4,T=1,value=
[Packet:LVL=2,VerSum=10,Ver=3,T=7,value=
[Packet:LVL=3,VerSum=1,Ver=1,T=4,value=208],
[Packet:LVL=3,VerSum=6,Ver=6,T=4,value=208]],
[Packet:LVL=2,VerSum=2,Ver=2,T=4,value=54640]],
[Packet:LVL=1,VerSum=16,Ver=4,T=1,value=
[Packet:LVL=2,VerSum=0,Ver=0,T=4,value=41],
[Packet:LVL=2,VerSum=1,Ver=1,T=4,value=169],
[Packet:LVL=2,VerSum=4,Ver=4,T=4,value=213],
[Packet:LVL=2,VerSum=7,Ver=7,T=4,value=246]],
[Packet:LVL=1,VerSum=16,Ver=2,T=1,value=
[Packet:LVL=2,VerSum=12,Ver=7,T=6,value=
[Packet:LVL=3,VerSum=1,Ver=1,T=4,value=34],
[Packet:LVL=3,VerSum=4,Ver=4,T=4,value=34]],
[Packet:LVL=2,VerSum=2,Ver=2,T=4,value=31562]],
[Packet:LVL=1,VerSum=7,Ver=2,T=0,value=
[Packet:LVL=2,VerSum=5,Ver=5,T=4,value=1625637177]],
[Packet:LVL=1,VerSum=15,Ver=2,T=3,value=
[Packet:LVL=2,VerSum=6,Ver=6,T=4,value=852],
[Packet:LVL=2,VerSum=0,Ver=0,T=4,value=650304435],
[Packet:LVL=2,VerSum=3,Ver=3,T=4,value=1],
[Packet:LVL=2,VerSum=1,Ver=1,T=4,value=651481],
[Packet:LVL=2,VerSum=3,Ver=3,T=4,value=70]],
[Packet:LVL=1,VerSum=26,Ver=6,T=0,value=
[Packet:LVL=2,VerSum=4,Ver=4,T=4,value=409369],
[Packet:LVL=2,VerSum=2,Ver=2,T=4,value=4146254],
[Packet:LVL=2,VerSum=4,Ver=4,T=4,value=19617],
[Packet:LVL=2,VerSum=7,Ver=7,T=4,value=217],
[Packet:LVL=2,VerSum=3,Ver=3,T=4,value=45]],
[Packet:LVL=1,VerSum=4,Ver=4,T=4,value=13360882],
[Packet:LVL=1,VerSum=5,Ver=0,T=1,value=
[Packet:LVL=2,VerSum=1,Ver=1,T=4,value=118],
[Packet:LVL=2,VerSum=4,Ver=4,T=4,value=106],
[Packet:LVL=2,VerSum=0,Ver=0,T=4,value=171]],
[Packet:LVL=1,VerSum=3,Ver=3,T=4,value=10570687],
[Packet:LVL=1,VerSum=17,Ver=4,T=1,value=
[Packet:LVL=2,VerSum=11,Ver=0,T=6,value=
[Packet:LVL=3,VerSum=6,Ver=6,T=4,value=33],
[Packet:LVL=3,VerSum=5,Ver=5,T=4,value=3854067120]],
[Packet:LVL=2,VerSum=2,Ver=2,T=4,value=2456541]],
[Packet:LVL=1,VerSum=18,Ver=4,T=3,value=
[Packet:LVL=2,VerSum=4,Ver=4,T=4,value=55],
[Packet:LVL=2,VerSum=3,Ver=3,T=4,value=42444],
[Packet:LVL=2,VerSum=7,Ver=7,T=4,value=6]],
[Packet:LVL=1,VerSum=48,Ver=0,T=1,value=
[Packet:LVL=2,VerSum=45,Ver=3,T=6,value=
[Packet:LVL=3,VerSum=22,Ver=5,T=0,value=
[Packet:LVL=4,VerSum=7,Ver=7,T=4,value=15],
[Packet:LVL=4,VerSum=6,Ver=6,T=4,value=3],
[Packet:LVL=4,VerSum=4,Ver=4,T=4,value=6]],
[Packet:LVL=3,VerSum=20,Ver=4,T=0,value=
[Packet:LVL=4,VerSum=7,Ver=7,T=4,value=5],
[Packet:LVL=4,VerSum=6,Ver=6,T=4,value=12],
[Packet:LVL=4,VerSum=3,Ver=3,T=4,value=5]]],
[Packet:LVL=2,VerSum=3,Ver=3,T=4,value=5833350]],
[Packet:LVL=1,VerSum=15,Ver=3,T=1,value=
[Packet:LVL=2,VerSum=12,Ver=7,T=6,value=
[Packet:LVL=3,VerSum=3,Ver=3,T=4,value=2729],
[Packet:LVL=3,VerSum=2,Ver=2,T=4,value=15305503]],
[Packet:LVL=2,VerSum=0,Ver=0,T=4,value=101077955]],
[Packet:LVL=1,VerSum=16,Ver=5,T=0,value=
[Packet:LVL=2,VerSum=2,Ver=2,T=4,value=155057593],
[Packet:LVL=2,VerSum=3,Ver=3,T=4,value=13],
[Packet:LVL=2,VerSum=0,Ver=0,T=4,value=37107853833],
[Packet:LVL=2,VerSum=6,Ver=6,T=4,value=5]],
[Packet:LVL=1,VerSum=18,Ver=6,T=2,value=
[Packet:LVL=2,VerSum=7,Ver=7,T=4,value=10082448],
[Packet:LVL=2,VerSum=2,Ver=2,T=4,value=410034],
[Packet:LVL=2,VerSum=3,Ver=3,T=4,value=1891]],
[Packet:LVL=1,VerSum=10,Ver=5,T=1,value=
[Packet:LVL=2,VerSum=5,Ver=5,T=4,value=138]],
[Packet:LVL=1,VerSum=6,Ver=6,T=4,value=497655],
[Packet:LVL=1,VerSum=13,Ver=7,T=2,value=
[Packet:LVL=2,VerSum=6,Ver=6,T=4,value=3]],
[Packet:LVL=1,VerSum=4,Ver=4,T=4,value=42002],
[Packet:LVL=1,VerSum=43,Ver=1,T=1,value=
[Packet:LVL=2,VerSum=3,Ver=3,T=4,value=18874],
[Packet:LVL=2,VerSum=39,Ver=3,T=5,value=
[Packet:LVL=3,VerSum=14,Ver=3,T=0,value=
[Packet:LVL=4,VerSum=7,Ver=7,T=4,value=12],
[Packet:LVL=4,VerSum=4,Ver=4,T=4,value=5],
[Packet:LVL=4,VerSum=0,Ver=0,T=4,value=12]],
[Packet:LVL=3,VerSum=22,Ver=7,T=0,value=
[Packet:LVL=4,VerSum=2,Ver=2,T=4,value=8],
[Packet:LVL=4,VerSum=7,Ver=7,T=4,value=6],
[Packet:LVL=4,VerSum=6,Ver=6,T=4,value=11]]]],
[Packet:LVL=1,VerSum=3,Ver=3,T=4,value=9],
[Packet:LVL=1,VerSum=22,Ver=7,T=1,value=
[Packet:LVL=2,VerSum=14,Ver=5,T=7,value=
[Packet:LVL=3,VerSum=4,Ver=4,T=4,value=35175563],
[Packet:LVL=3,VerSum=5,Ver=5,T=4,value=133]],
[Packet:LVL=2,VerSum=1,Ver=1,T=4,value=3584]],
[Packet:LVL=1,VerSum=16,Ver=1,T=1,value=
[Packet:LVL=2,VerSum=7,Ver=7,T=4,value=3683],
[Packet:LVL=2,VerSum=8,Ver=1,T=6,value=
[Packet:LVL=3,VerSum=4,Ver=4,T=4,value=248005212],
[Packet:LVL=3,VerSum=3,Ver=3,T=4,value=248005212]]],
[Packet:LVL=1,VerSum=52,Ver=6,T=1,value=
[Packet:LVL=2,VerSum=12,Ver=4,T=0,value=
[Packet:LVL=3,VerSum=6,Ver=6,T=4,value=15],
[Packet:LVL=3,VerSum=2,Ver=2,T=4,value=4],
[Packet:LVL=3,VerSum=0,Ver=0,T=4,value=11]],
[Packet:LVL=2,VerSum=14,Ver=4,T=0,value=
[Packet:LVL=3,VerSum=3,Ver=3,T=4,value=11],
[Packet:LVL=3,VerSum=1,Ver=1,T=4,value=12],
[Packet:LVL=3,VerSum=6,Ver=6,T=4,value=14]],
[Packet:LVL=2,VerSum=20,Ver=6,T=0,value=
[Packet:LVL=3,VerSum=6,Ver=6,T=4,value=10],
[Packet:LVL=3,VerSum=6,Ver=6,T=4,value=10],
[Packet:LVL=3,VerSum=2,Ver=2,T=4,value=8]]],
[Packet:LVL=1,VerSum=16,Ver=1,T=1,value=
[Packet:LVL=2,VerSum=13,Ver=7,T=6,value=
[Packet:LVL=3,VerSum=2,Ver=2,T=4,value=1217],
[Packet:LVL=3,VerSum=4,Ver=4,T=4,value=151]],
[Packet:LVL=2,VerSum=2,Ver=2,T=4,value=588931]],
[Packet:LVL=1,VerSum=7,Ver=7,T=4,value=4],
[Packet:LVL=1,VerSum=20,Ver=3,T=0,value=
[Packet:LVL=2,VerSum=5,Ver=5,T=4,value=48],
[Packet:LVL=2,VerSum=7,Ver=7,T=4,value=45472],
[Packet:LVL=2,VerSum=5,Ver=5,T=4,value=94453890]],
[Packet:LVL=1,VerSum=48,Ver=4,T=0,value=
[Packet:LVL=2,VerSum=15,Ver=6,T=1,value=
[Packet:LVL=3,VerSum=2,Ver=2,T=4,value=7],
[Packet:LVL=3,VerSum=4,Ver=4,T=4,value=12],
[Packet:LVL=3,VerSum=3,Ver=3,T=4,value=5]],
[Packet:LVL=2,VerSum=16,Ver=4,T=1,value=
[Packet:LVL=3,VerSum=6,Ver=6,T=4,value=13],
[Packet:LVL=3,VerSum=5,Ver=5,T=4,value=5],
[Packet:LVL=3,VerSum=1,Ver=1,T=4,value=15]],
[Packet:LVL=2,VerSum=13,Ver=0,T=1,value=
[Packet:LVL=3,VerSum=1,Ver=1,T=4,value=7],
[Packet:LVL=3,VerSum=5,Ver=5,T=4,value=13],
[Packet:LVL=3,VerSum=7,Ver=7,T=4,value=9]]],
[Packet:LVL=1,VerSum=4,Ver=2,T=1,value=
[Packet:LVL=2,VerSum=0,Ver=0,T=4,value=164],
[Packet:LVL=2,VerSum=2,Ver=2,T=4,value=165]],
[Packet:LVL=1,VerSum=18,Ver=6,T=1,value=
[Packet:LVL=2,VerSum=6,Ver=6,T=4,value=59825],
[Packet:LVL=2,VerSum=6,Ver=3,T=5,value=
[Packet:LVL=3,VerSum=2,Ver=2,T=4,value=3724],
[Packet:LVL=3,VerSum=1,Ver=1,T=4,value=956760]]],
[Packet:LVL=1,VerSum=80,Ver=7,T=0,value=
[Packet:LVL=2,VerSum=73,Ver=4,T=3,value=
[Packet:LVL=3,VerSum=69,Ver=0,T=3,value=
[Packet:LVL=4,VerSum=69,Ver=6,T=1,value=
[Packet:LVL=5,VerSum=63,Ver=1,T=1,value=
[Packet:LVL=6,VerSum=62,Ver=1,T=1,value=
[Packet:LVL=7,VerSum=61,Ver=3,T=3,value=
[Packet:LVL=8,VerSum=58,Ver=6,T=3,value=
[Packet:LVL=9,VerSum=52,Ver=6,T=0,value=
[Packet:LVL=10,VerSum=46,Ver=0,T=1,value=
[Packet:LVL=11,VerSum=46,Ver=2,T=0,value=
[Packet:LVL=12,VerSum=44,Ver=2,T=0,value=
[Packet:LVL=13,VerSum=42,Ver=7,T=2,value=
[Packet:LVL=14,VerSum=35,Ver=5,T=2,value=
[Packet:LVL=15,VerSum=30,Ver=4,T=2,value=
[Packet:LVL=16,VerSum=26,Ver=6,T=0,value=
[Packet:LVL=17,VerSum=20,Ver=4,T=0,value=
[Packet:LVL=18,VerSum=16,Ver=4,T=2,value=
[Packet:LVL=19,VerSum=12,Ver=1,T=2,value=
[Packet:LVL=20,VerSum=11,Ver=4,T=2,value=
[Packet:LVL=21,VerSum=7,Ver=7,T=4,value=3547]]]]]]]]]]]]]]]]]]]]],
[Packet:LVL=1,VerSum=9,Ver=0,T=0,value=
[Packet:LVL=2,VerSum=6,Ver=6,T=4,value=2],
[Packet:LVL=2,VerSum=3,Ver=3,T=4,value=101374]],
[Packet:LVL=1,VerSum=33,Ver=3,T=1,value=
[Packet:LVL=2,VerSum=3,Ver=3,T=4,value=2788],
[Packet:LVL=2,VerSum=27,Ver=6,T=5,value=
[Packet:LVL=3,VerSum=12,Ver=2,T=0,value=
[Packet:LVL=4,VerSum=7,Ver=7,T=4,value=6],
[Packet:LVL=4,VerSum=2,Ver=2,T=4,value=9],
[Packet:LVL=4,VerSum=1,Ver=1,T=4,value=9]],
[Packet:LVL=3,VerSum=9,Ver=0,T=0,value=
[Packet:LVL=4,VerSum=4,Ver=4,T=4,value=13],
[Packet:LVL=4,VerSum=4,Ver=4,T=4,value=2],
[Packet:LVL=4,VerSum=1,Ver=1,T=4,value=15]]]],
[Packet:LVL=1,VerSum=18,Ver=4,T=2,value=
[Packet:LVL=2,VerSum=0,Ver=0,T=4,value=3685],
[Packet:LVL=2,VerSum=1,Ver=1,T=4,value=7582],
[Packet:LVL=2,VerSum=2,Ver=2,T=4,value=81],
[Packet:LVL=2,VerSum=6,Ver=6,T=4,value=701716],
[Packet:LVL=2,VerSum=5,Ver=5,T=4,value=429274]],
[Packet:LVL=1,VerSum=34,Ver=0,T=1,value=
[Packet:LVL=2,VerSum=30,Ver=3,T=6,value=
[Packet:LVL=3,VerSum=12,Ver=3,T=0,value=
[Packet:LVL=4,VerSum=1,Ver=1,T=4,value=11],
[Packet:LVL=4,VerSum=7,Ver=7,T=4,value=9],
[Packet:LVL=4,VerSum=1,Ver=1,T=4,value=10]],
[Packet:LVL=3,VerSum=15,Ver=5,T=0,value=
[Packet:LVL=4,VerSum=1,Ver=1,T=4,value=12],
[Packet:LVL=4,VerSum=4,Ver=4,T=4,value=5],
[Packet:LVL=4,VerSum=5,Ver=5,T=4,value=14]]],
[Packet:LVL=2,VerSum=4,Ver=4,T=4,value=66]],
[Packet:LVL=1,VerSum=14,Ver=1,T=1,value=
[Packet:LVL=2,VerSum=3,Ver=3,T=4,value=158],
[Packet:LVL=2,VerSum=10,Ver=5,T=6,value=
[Packet:LVL=3,VerSum=2,Ver=2,T=4,value=123061340],
[Packet:LVL=3,VerSum=3,Ver=3,T=4,value=309]]],
[Packet:LVL=1,VerSum=2,Ver=1,T=2,value=
[Packet:LVL=2,VerSum=1,Ver=1,T=4,value=265210578],
[Packet:LVL=2,VerSum=0,Ver=0,T=4,value=10]],
[Packet:LVL=1,VerSum=7,Ver=7,T=4,value=31918501],
[Packet:LVL=1,VerSum=28,Ver=4,T=1,value=
[Packet:LVL=2,VerSum=4,Ver=4,T=4,value=205],
[Packet:LVL=2,VerSum=2,Ver=2,T=4,value=109],
[Packet:LVL=2,VerSum=5,Ver=5,T=4,value=187],
[Packet:LVL=2,VerSum=7,Ver=7,T=4,value=92],
[Packet:LVL=2,VerSum=6,Ver=6,T=4,value=159]],
[Packet:LVL=1,VerSum=13,Ver=0,T=2,value=
[Packet:LVL=2,VerSum=7,Ver=7,T=4,value=29305],
[Packet:LVL=2,VerSum=3,Ver=3,T=4,value=2195],
[Packet:LVL=2,VerSum=3,Ver=3,T=4,value=98863220],
[Packet:LVL=2,VerSum=0,Ver=0,T=4,value=15518495373]],
[Packet:LVL=1,VerSum=22,Ver=3,T=1,value=
[Packet:LVL=2,VerSum=12,Ver=5,T=5,value=
[Packet:LVL=3,VerSum=6,Ver=6,T=4,value=491281],
[Packet:LVL=3,VerSum=1,Ver=1,T=4,value=491281]],
[Packet:LVL=2,VerSum=7,Ver=7,T=4,value=49105]],
[Packet:LVL=1,VerSum=22,Ver=6,T=1,value=
[Packet:LVL=2,VerSum=11,Ver=4,T=5,value=
[Packet:LVL=3,VerSum=5,Ver=5,T=4,value=3696],
[Packet:LVL=3,VerSum=2,Ver=2,T=4,value=81611779]],
[Packet:LVL=2,VerSum=5,Ver=5,T=4,value=51781]],
[Packet:LVL=1,VerSum=5,Ver=5,T=3,value=
[Packet:LVL=2,VerSum=0,Ver=0,T=4,value=11],
[Packet:LVL=2,VerSum=0,Ver=0,T=4,value=14349575]]]
21 levels deep!!
TFTO.