#!/usr/bin/env python3 import sys from bitstring import BitArray from operator import mul from functools import reduce def parse_packet(packet, s, np=100000000, length=1000000000): nex = s end = s+length-1 bv = 0 numbers = [] while np > 0 and nex < min(len(packet)+1,end): if (len(packet[nex:end+1]) == 0 or int(''.join(packet[nex:end+1]),2) == 0 or int(''.join(packet[nex:]),2) == 0): if length < 1000000000: nex = end+1 break v = int(''.join(packet[nex:nex+3]),2) bv += v t = int(''.join(packet[nex+3:nex+6]),2) nex += 6 if t == 4: num = [] while (n := packet[nex]) == '1': num.append(list(packet[nex+1:nex+5])) nex += 5 num.append(list(packet[nex+1:nex+5])) nex += 5 i = int(''.join([''.join(n) for n in num]),2) numbers.append(i) else: I = packet[nex] nex += 1 if I == '1': l = int(''.join(packet[nex:nex+11]),2) nex += 11 b, nex, numbs = parse_packet(packet, nex, np=l) bv += b elif I == '0': l = int(''.join(packet[nex:nex+15]),2) nex += 15 b, nex, numbs = parse_packet(packet, nex, length=l) bv += b if t == 0: numbers.append(sum(numbs)) elif t == 1: numbers.append(reduce(mul, numbs, 1)) elif t == 2: numbers.append(min(numbs)) elif t == 3: numbers.append(max(numbs)) elif t == 5: numbers.append(int(numbs[0] > numbs[1])) elif t == 6: numbers.append(int(numbs[0] < numbs[1])) elif t == 7: numbers.append(int(numbs[0] == numbs[1])) np -= 1 return bv, nex, numbers if __name__ == '__main__': hexa = [list(line.strip('\n')) for line in open(sys.argv[1])] bits = [list(BitArray(hex=c).bin) for c in hexa[0]] bits = [b for l in bits for b in l] bv, _, num = parse_packet(bits,0,np=1) # challenge 1 res1 = str(bv) print("challenge 1:" + "\n" + res1 + "\n") # challenge 2 res2 = str(num[0]) print("challenge 2:" + "\n" + res2 + "\n")