Day 16
This commit is contained in:
86
day16/generator.py
Normal file
86
day16/generator.py
Normal 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
11
day16/input.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
D2FE28
|
||||
38006F45291200
|
||||
EE00D40C823060
|
||||
8A004A801A8002F478
|
||||
620080001611562C8802118E34
|
||||
C0015000016115A2E0802F182340
|
||||
A0016C880162017C3686B18A3D4780
|
||||
#
|
||||
6006040002F127E459CCED24001C89FF6DAE4E9281C8003913FEDB5C9D250390007227FDB6B93A4A072000E44FFB6D7274940E
|
||||
#
|
||||
6051639005B56008C1D9BB3CC9DAD5BE97A4A9104700AE76E672DC95AAE91425EF6AD8BA5591C00F92073004AC0171007E0BC248BE0008645982B1CA680A7A0CC60096802723C94C265E5B9699E7E94D6070C016958F99AC015100760B45884600087C6E88B091C014959C83E740440209FC89C2896A50765A59CE299F3640D300827902547661964D2239180393AF92A8B28F4401BCC8ED52C01591D7E9D2591D7E9D273005A5D127C99802C095B044D5A19A73DC0E9C553004F000DE953588129E372008F2C0169FDB44FA6C9219803E00085C378891F00010E8FF1AE398803D1BE25C743005A6477801F59CC4FA1F3989F420C0149ED9CF006A000084C5386D1F4401F87310E313804D33B4095AFBED32ABF2CA28007DC9D3D713300524BCA940097CA8A4AF9F4C00F9B6D00088654867A7BC8BCA4829402F9D6895B2E4DF7E373189D9BE6BF86B200B7E3C68021331CD4AE6639A974232008E663C3FE00A4E0949124ED69087A848002749002151561F45B3007218C7A8FE600FC228D50B8C01097EEDD7001CF9DE5C0E62DEB089805330ED30CD3C0D3A3F367A40147E8023221F221531C9681100C717002100B36002A19809D15003900892601F950073630024805F400150D400A70028C00F5002C00252600698400A700326C0E44590039687B313BF669F35C9EF974396EF0A647533F2011B340151007637C46860200D43085712A7E4FE60086003E5234B5A56129C91FC93F1802F12EC01292BD754BCED27B92BD754BCED27B100264C4C40109D578CA600AC9AB5802B238E67495391D5CFC402E8B325C1E86F266F250B77ECC600BE006EE00085C7E8DF044001088E31420BCB08A003A72BF87D7A36C994CE76545030047801539F649BF4DEA52CBCA00B4EF3DE9B9CFEE379F14608
|
||||
18
day16/part1.py
Normal file
18
day16/part1.py
Normal 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
39
day16/part2.py
Normal 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
48
day16/shared.py
Normal 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
|
||||
Reference in New Issue
Block a user