From 6ff4a25bf37b1a96b2664aa6d6d431b374a08c7e Mon Sep 17 00:00:00 2001 From: Sebastian Seedorf Date: Fri, 17 Dec 2021 11:29:35 +0100 Subject: [PATCH] Day 16 --- day16/generator.py | 86 ++++++++++++++++++++++++++++++++++++++++++++++ day16/input.txt | 11 ++++++ day16/part1.py | 18 ++++++++++ day16/part2.py | 39 +++++++++++++++++++++ day16/shared.py | 48 ++++++++++++++++++++++++++ 5 files changed, 202 insertions(+) create mode 100644 day16/generator.py create mode 100644 day16/input.txt create mode 100644 day16/part1.py create mode 100644 day16/part2.py create mode 100644 day16/shared.py diff --git a/day16/generator.py b/day16/generator.py new file mode 100644 index 0000000..939e619 --- /dev/null +++ b/day16/generator.py @@ -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) + ]) + ]) +)) diff --git a/day16/input.txt b/day16/input.txt new file mode 100644 index 0000000..f063d2b --- /dev/null +++ b/day16/input.txt @@ -0,0 +1,11 @@ +D2FE28 +38006F45291200 +EE00D40C823060 +8A004A801A8002F478 +620080001611562C8802118E34 +C0015000016115A2E0802F182340 +A0016C880162017C3686B18A3D4780 +# +6006040002F127E459CCED24001C89FF6DAE4E9281C8003913FEDB5C9D250390007227FDB6B93A4A072000E44FFB6D7274940E +# +6051639005B56008C1D9BB3CC9DAD5BE97A4A9104700AE76E672DC95AAE91425EF6AD8BA5591C00F92073004AC0171007E0BC248BE0008645982B1CA680A7A0CC60096802723C94C265E5B9699E7E94D6070C016958F99AC015100760B45884600087C6E88B091C014959C83E740440209FC89C2896A50765A59CE299F3640D300827902547661964D2239180393AF92A8B28F4401BCC8ED52C01591D7E9D2591D7E9D273005A5D127C99802C095B044D5A19A73DC0E9C553004F000DE953588129E372008F2C0169FDB44FA6C9219803E00085C378891F00010E8FF1AE398803D1BE25C743005A6477801F59CC4FA1F3989F420C0149ED9CF006A000084C5386D1F4401F87310E313804D33B4095AFBED32ABF2CA28007DC9D3D713300524BCA940097CA8A4AF9F4C00F9B6D00088654867A7BC8BCA4829402F9D6895B2E4DF7E373189D9BE6BF86B200B7E3C68021331CD4AE6639A974232008E663C3FE00A4E0949124ED69087A848002749002151561F45B3007218C7A8FE600FC228D50B8C01097EEDD7001CF9DE5C0E62DEB089805330ED30CD3C0D3A3F367A40147E8023221F221531C9681100C717002100B36002A19809D15003900892601F950073630024805F400150D400A70028C00F5002C00252600698400A700326C0E44590039687B313BF669F35C9EF974396EF0A647533F2011B340151007637C46860200D43085712A7E4FE60086003E5234B5A56129C91FC93F1802F12EC01292BD754BCED27B92BD754BCED27B100264C4C40109D578CA600AC9AB5802B238E67495391D5CFC402E8B325C1E86F266F250B77ECC600BE006EE00085C7E8DF044001088E31420BCB08A003A72BF87D7A36C994CE76545030047801539F649BF4DEA52CBCA00B4EF3DE9B9CFEE379F14608 diff --git a/day16/part1.py b/day16/part1.py new file mode 100644 index 0000000..8490f50 --- /dev/null +++ b/day16/part1.py @@ -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)) + diff --git a/day16/part2.py b/day16/part2.py new file mode 100644 index 0000000..c07e960 --- /dev/null +++ b/day16/part2.py @@ -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])) diff --git a/day16/shared.py b/day16/shared.py new file mode 100644 index 0000000..30f849f --- /dev/null +++ b/day16/shared.py @@ -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 \ No newline at end of file