diff --git a/16/16.py b/16/16.py new file mode 100644 index 0000000..4fe51eb --- /dev/null +++ b/16/16.py @@ -0,0 +1,122 @@ +import sys +from math import prod + +LITERAL = 4 +OPERATOR = { + 0: sum, + 1: prod, + 2: min, + 3: max, + 5: lambda lst: int(lst[0] > lst[1]), + 6: lambda lst: int(lst[0] < lst[1]), + 7: lambda lst: int(lst[0] == lst[1]), +} + +total_version = 0 + + +def read_bits(bits, start, n) -> tuple[str, int]: + end = start + n + return bits[start:end], end + + +def read_bits_int(bits, start, n) -> tuple[int, int]: + number_bits, pos = read_bits(bits, start, n) + return int(number_bits, base=2), pos + + +def hex_to_bits(hex: str) -> str: + return format(int(hex, base=16), "04b") + + +def hex_string_to_bit_string(hex_string: str) -> str: + return "".join([hex_to_bits(x) for x in list(hex_string)]) + + +def parse_packet(bits) -> int: + pos = 0 + packet_version, _ = read_bits_int(bits, pos, 3) + + global total_version + total_version += packet_version + + type_ID, _ = read_bits_int(bits[3:], pos, 3) + + if type_ID == LITERAL: + # print("Found: literal") + value, next_pos = parse_literal(bits[pos:]) + # print("literal:", value) + else: + # print("found: operator") + value, next_pos = parse_operator(bits[pos:]) + + pos += next_pos + + return value, pos + + +def parse_literal(bits) -> tuple[int, int]: + pos = 0 + packet_version, pos = read_bits_int(bits, pos, 3) + + type_ID, pos = read_bits_int(bits, pos, 3) + + number = "" + + done = False + + while not done: + part, pos = read_bits(bits, pos, 5) + + if part[0] == "0": + done = True + + number += part[1:] + + return int(number, base=2), pos + + +def parse_operator(bits) -> int: + pos = 0 + packet_version, pos = read_bits_int(bits, pos, 3) + type_ID, pos = read_bits_int(bits, pos, 3) + + length_type_id = bits[6] + + pos = 7 + + parts = [] + + if length_type_id == "0": + total_length, pos = read_bits_int(bits, pos, 15) + # print("total length:", total_length) + read = 0 + + while read != total_length: + value, just_read = parse_packet(bits[pos:]) + read += just_read + # print(f"Length was: {just_read}, total: {read} of {total_length}") + pos += just_read + parts.append(value) + else: + number_of_subs, pos = read_bits_int(bits, pos, 11) + # print("number of subs:", number_of_subs) + + for i in range(number_of_subs): + value, next_pos = parse_packet(bits[pos:]) + parts.append(value) + pos += next_pos + + calculated = OPERATOR[type_ID](parts) + + return calculated, pos + + +if __name__ == "__main__": + hex_string = sys.stdin.readline().strip() + bits = hex_string_to_bit_string(hex_string) + + value, _ = parse_operator(bits) + + print("part one:", total_version) + print("part two:", value) diff --git a/16/ex16.in b/16/ex16.in new file mode 100644 index 0000000..e69de29 diff --git a/16/input16.in b/16/input16.in new file mode 100644 index 0000000..2e4a973 --- /dev/null +++ b/16/input16.in @@ -0,0 +1 @@ +6051639005B56008C1D9BB3CC9DAD5BE97A4A9104700AE76E672DC95AAE91425EF6AD8BA5591C00F92073004AC0171007E0BC248BE0008645982B1CA680A7A0CC60096802723C94C265E5B9699E7E94D6070C016958F99AC015100760B45884600087C6E88B091C014959C83E740440209FC89C2896A50765A59CE299F3640D300827902547661964D2239180393AF92A8B28F4401BCC8ED52C01591D7E9D2591D7E9D273005A5D127C99802C095B044D5A19A73DC0E9C553004F000DE953588129E372008F2C0169FDB44FA6C9219803E00085C378891F00010E8FF1AE398803D1BE25C743005A6477801F59CC4FA1F3989F420C0149ED9CF006A000084C5386D1F4401F87310E313804D33B4095AFBED32ABF2CA28007DC9D3D713300524BCA940097CA8A4AF9F4C00F9B6D00088654867A7BC8BCA4829402F9D6895B2E4DF7E373189D9BE6BF86B200B7E3C68021331CD4AE6639A974232008E663C3FE00A4E0949124ED69087A848002749002151561F45B3007218C7A8FE600FC228D50B8C01097EEDD7001CF9DE5C0E62DEB089805330ED30CD3C0D3A3F367A40147E8023221F221531C9681100C717002100B36002A19809D15003900892601F950073630024805F400150D400A70028C00F5002C00252600698400A700326C0E44590039687B313BF669F35C9EF974396EF0A647533F2011B340151007637C46860200D43085712A7E4FE60086003E5234B5A56129C91FC93F1802F12EC01292BD754BCED27B92BD754BCED27B100264C4C40109D578CA600AC9AB5802B238E67495391D5CFC402E8B325C1E86F266F250B77ECC600BE006EE00085C7E8DF044001088E31420BCB08A003A72BF87D7A36C994CE76545030047801539F649BF4DEA52CBCA00B4EF3DE9B9CFEE379F14608