This commit is contained in:
Sebastian Seedorf
2021-12-17 11:29:35 +01:00
parent 18c76f694b
commit 6ff4a25bf3
5 changed files with 202 additions and 0 deletions

86
day16/generator.py Normal file
View File

@@ -0,0 +1,86 @@
import random
def int_to_bin(num, l):
return bin(num)[2:].zfill(l)
def literal(ver, num):
bin_num = bin(num)[2:]
bin_num = bin_num.zfill((len(bin_num)+3) // 4 * 4)
return int_to_bin(ver, 3) + int_to_bin(4, 3) + ''.join(('1' if i+4 < len(bin_num) else "0") + bin_num[i:i+4] for i in range(0, len(bin_num), 4))
def sub_by_length(ver, op, subs):
bin_sub = ''.join(subs)
bin_len = int_to_bin(len(bin_sub), 15)
return int_to_bin(ver, 3) + int_to_bin(op, 3) + '0' + bin_len + bin_sub
def sub_by_amount(ver, op, subs):
bin_sub = ''.join(subs)
bin_len = int_to_bin(len(subs), 11)
return int_to_bin(ver, 3) + int_to_bin(op, 3) + '1' + bin_len + bin_sub
def bin_to_hex(bin_num):
pad_len = (len(bin_num)+7) // 8 * 8 - len(bin_num)
bin_num = bin_num + '0' * pad_len
return ''.join(hex(int(bin_num[i:i+4], 2))[2:] for i in range(0, len(bin_num), 4)).upper()
print(bin_to_hex(
literal(6, 2021)
) == 'D2FE28')
print(bin_to_hex(
sub_by_length(1, 6, [
literal(6, 10),
literal(2, 20)
])
) == '38006F45291200')
print(bin_to_hex(
sub_by_amount(7, 3, [
literal(2, 1),
literal(4, 2),
literal(1, 3)
])
) == 'EE00D40C823060')
print(bin_to_hex(
sub_by_amount(4, 2, [
sub_by_amount(1, 2, [
sub_by_length(5, 2, [
literal(6, 15)
])
])
])
) == '8A004A801A8002F478')
print(bin_to_hex(
sub_by_amount(3, 0, [
sub_by_length(0, 0, [
literal(0, 10),
literal(5, 11)
]),
sub_by_amount(1, 0, [
literal(0, 12),
literal(3, 13)
])
])
) == '620080001611562C8802118E34')
print(bin_to_hex(
sub_by_length(3, 0, [
sub_by_length(0, 0, [
literal(0, 1000),
literal(5, 51641)
]),
sub_by_length(1, 0, [
literal(0, 65213),
literal(3, 213511)
]),
sub_by_length(1, 0, [
literal(0, 65213),
literal(3, 213511)
]),
sub_by_length(1, 0, [
literal(0, 65213),
literal(3, 213511)
]),
sub_by_length(1, 0, [
literal(0, 65213),
literal(3, 213511)
])
])
))

11
day16/input.txt Normal file
View File

@@ -0,0 +1,11 @@
D2FE28
38006F45291200
EE00D40C823060
8A004A801A8002F478
620080001611562C8802118E34
C0015000016115A2E0802F182340
A0016C880162017C3686B18A3D4780
#
6006040002F127E459CCED24001C89FF6DAE4E9281C8003913FEDB5C9D250390007227FDB6B93A4A072000E44FFB6D7274940E
#
6051639005B56008C1D9BB3CC9DAD5BE97A4A9104700AE76E672DC95AAE91425EF6AD8BA5591C00F92073004AC0171007E0BC248BE0008645982B1CA680A7A0CC60096802723C94C265E5B9699E7E94D6070C016958F99AC015100760B45884600087C6E88B091C014959C83E740440209FC89C2896A50765A59CE299F3640D300827902547661964D2239180393AF92A8B28F4401BCC8ED52C01591D7E9D2591D7E9D273005A5D127C99802C095B044D5A19A73DC0E9C553004F000DE953588129E372008F2C0169FDB44FA6C9219803E00085C378891F00010E8FF1AE398803D1BE25C743005A6477801F59CC4FA1F3989F420C0149ED9CF006A000084C5386D1F4401F87310E313804D33B4095AFBED32ABF2CA28007DC9D3D713300524BCA940097CA8A4AF9F4C00F9B6D00088654867A7BC8BCA4829402F9D6895B2E4DF7E373189D9BE6BF86B200B7E3C68021331CD4AE6639A974232008E663C3FE00A4E0949124ED69087A848002749002151561F45B3007218C7A8FE600FC228D50B8C01097EEDD7001CF9DE5C0E62DEB089805330ED30CD3C0D3A3F367A40147E8023221F221531C9681100C717002100B36002A19809D15003900892601F950073630024805F400150D400A70028C00F5002C00252600698400A700326C0E44590039687B313BF669F35C9EF974396EF0A647533F2011B340151007637C46860200D43085712A7E4FE60086003E5234B5A56129C91FC93F1802F12EC01292BD754BCED27B92BD754BCED27B100264C4C40109D578CA600AC9AB5802B238E67495391D5CFC402E8B325C1E86F266F250B77ECC600BE006EE00085C7E8DF044001088E31420BCB08A003A72BF87D7A36C994CE76545030047801539F649BF4DEA52CBCA00B4EF3DE9B9CFEE379F14608

18
day16/part1.py Normal file
View File

@@ -0,0 +1,18 @@
#!/usr/bin/env python3
from day16.shared import parse_packets
lines = (x.strip() for x in open("input.txt"))
def sum_version(exprs):
return sum(expr[0] + (sum_version(expr[2]) if isinstance(expr[2], list) else 0) for expr in exprs)
for line in lines:
print("NEW LINE:", line)
if line[0] == '#':
continue
bin_string = ''.join(bin(int(c, 16))[2:].zfill(4) for c in line)
parsed = parse_packets(bin_string)
print(sum_version(parsed))

39
day16/part2.py Normal file
View File

@@ -0,0 +1,39 @@
#!/usr/bin/env python3
from functools import reduce
from operator import mul
from day16.shared import parse_packets
lines = (x.strip() for x in open("input.txt"))
def calc(expr):
_, op, value = expr
if op == 4:
return value
values = [calc(v) if isinstance(v, tuple) else v for v in value]
if op == 0:
return sum(values)
elif op == 1:
return reduce(mul, values)
elif op == 2:
return min(values)
elif op == 3:
return max(values)
elif op == 4:
return values
elif op == 5:
return 1 if values[0] > values[1] else 0
elif op == 6:
return 1 if values[0] < values[1] else 0
elif op == 7:
return 1 if values[0] == values[1] else 0
for line in lines:
print("NEW LINE:", line)
if line[0] == '#':
continue
bin_string = ''.join(bin(int(c, 16))[2:].zfill(4) for c in line)
parsed = parse_packets(bin_string)
print(calc(parsed[0]))

48
day16/shared.py Normal file
View File

@@ -0,0 +1,48 @@
def bin_to_int(bin_num):
return int(bin_num, 2)
def parse_literal(bin_num):
res = ""
i = 0
while True:
res += bin_num[i+1:i+5]
i += 5
if bin_num[i-5] == '0':
break
return bin_to_int(res), i
def parse_op(bin_num):
if bin_num[0] == '0':
length = bin_to_int(bin_num[1:16])
return parse_packets(bin_num[16:16+length]), length+16
else:
amount = bin_to_int(bin_num[1:12])
pkgs = []
i = 0
for _ in range(amount):
pkg, length = parse_packet(bin_num[12+i:])
pkgs.append(pkg)
i += length
return pkgs, 12+i
def parse_packet(bin_num):
ver = bin_to_int(bin_num[:3])
op = bin_to_int(bin_num[3:6])
if op == 4:
value, length = parse_literal(bin_num[6:])
else:
value, length = parse_op(bin_num[6:])
return (ver, op, value), length + 6
def parse_packets(bin_num):
pkgs = []
i = 0
while '1' in bin_num[i:]:
pkg, length = parse_packet(bin_num[i:])
pkgs.append(pkg)
i += length
return pkgs