Added 2021 (python)
This commit is contained in:
1
2021/16/input
Normal file
1
2021/16/input
Normal file
@ -0,0 +1 @@
|
||||
40541D900AEDC01A88002191FE2F45D1006A2FC2388D278D4653E3910020F2E2F3E24C007ECD7ABA6A200E6E8017F92C934CFA0E5290B569CE0F4BA5180213D963C00DC40010A87905A0900021B0D624C34600906725FFCF597491C6008C01B0004223342488A200F4378C9198401B87311A0C0803E600FC4887F14CC01C8AF16A2010021D1260DC7530042C012957193779F96AD9B36100907A00980021513E3943600043225C1A8EB2C3040043CC3B1802B400D3CA4B8D3292E37C30600B325A541D979606E384B524C06008E802515A638A73A226009CDA5D8026200D473851150401E8BF16E2ACDFB7DCD4F5C02897A5288D299D89CA6AA672AD5118804F592FC5BE8037000042217C64876000874728550D4C0149F29D00524ACCD2566795A0D880432BEAC79995C86483A6F3B9F6833397DEA03E401004F28CD894B9C48A34BC371CF7AA840155E002012E21260923DC4C248035299ECEB0AC4DFC0179B864865CF8802F9A005E264C25372ABAC8DEA706009F005C32B7FCF1BF91CADFF3C6FE4B3FB073005A6F93B633B12E0054A124BEE9C570004B245126F6E11E5C0199BDEDCE589275C10027E97BE7EF330F126DF3817354FFC82671BB5402510C803788DFA009CAFB14ECDFE57D8A766F0001A74F924AC99678864725F253FD134400F9B5D3004A46489A00A4BEAD8F7F1F7497C39A0020F357618C71648032BB004E4BBC4292EF1167274F1AA0078902262B0D4718229C8608A5226528F86008CFA6E802F275E2248C65F3610066274CEA9A86794E58AA5E5BDE73F34945E2008D27D2278EE30C489B3D20336D00C2F002DF480AC820287D8096F700288082C001DE1400C50035005AA2013E5400B10028C009600A74001EF2004F8400C92B172801F0F4C0139B8E19A8017D96A510A7E698800EAC9294A6E985783A400AE4A2945E9170
|
128
2021/16/prog.py
Normal file
128
2021/16/prog.py
Normal file
@ -0,0 +1,128 @@
|
||||
VERBOSE = True
|
||||
def verbose(s = "", *args, **kwargs):
|
||||
if VERBOSE:
|
||||
print(s, *args, **kwargs)
|
||||
|
||||
def get_input(sample = False, part = 1):
|
||||
with open(f'sample_p{part}' if sample else 'input', 'r') as f:
|
||||
return int(f.readlines()[0].strip(), 16)
|
||||
|
||||
|
||||
def full_size(packet):
|
||||
return 4 * (len(hex(packet)) - 2)
|
||||
|
||||
def version(p, size):
|
||||
return p >> (size - 3)
|
||||
|
||||
def type(p, size):
|
||||
return (p >> (size - 6)) & 0b111
|
||||
|
||||
def literal(p, size):
|
||||
shift = size - 3 - 3
|
||||
res = 0
|
||||
while shift >= 0:
|
||||
shift -= 5
|
||||
res <<= 4
|
||||
res |= (p >> shift) & 0xF
|
||||
|
||||
if not ((p >> (shift + 4)) & 1):
|
||||
return res
|
||||
raise ValueError("couldn't parse literal value correctly")
|
||||
|
||||
def type_id(p, size):
|
||||
return (p >> (size - 7)) & 1
|
||||
|
||||
def len_subpackets(p, size):
|
||||
return (p >> (size - 3 - 3 - 1 - 15)) & 0x7FFF
|
||||
|
||||
def n_subpackets(p, size):
|
||||
return (p >> (size - 3 - 3 - 1 - 11)) & 0x7FF
|
||||
|
||||
def parse_packet(p, part = 1, size = -1):
|
||||
s = 6
|
||||
size = size if size != -1 else full_size(p)
|
||||
res = version(p, size)
|
||||
t = type(p, size)
|
||||
verbose(f"{version(p, size) = }, { type(p, size) = }")
|
||||
verbose(format(p, 'b').zfill(size))
|
||||
if t == 4:
|
||||
verbose(f"\tis literal")
|
||||
n = literal(p, size)
|
||||
s += 5 * (len(hex(n)) - 2)
|
||||
if part == 1:
|
||||
return s, version(p, size)
|
||||
else:
|
||||
return s, n
|
||||
|
||||
tid = type_id(p, size)
|
||||
s += 1
|
||||
ress = []
|
||||
# verbose(f"{tid = }")
|
||||
if tid == 0:
|
||||
s += 15
|
||||
tot_sub_size = len_subpackets(p, size)
|
||||
verbose("VVVTTTILLLLLLLLLLLLLLL")
|
||||
verbose(f"len of sub packs {tot_sub_size}")
|
||||
|
||||
|
||||
cur_sub_size = 0
|
||||
i = 0
|
||||
while cur_sub_size < tot_sub_size:
|
||||
verbose(f"scanning for {i = } (reducing {size} by {size - s - tot_sub_size})")
|
||||
new_pack = (p >> (size - s - tot_sub_size)) & ((1 << tot_sub_size - cur_sub_size) -1)
|
||||
sub_size, sub_res = parse_packet(new_pack, size = tot_sub_size - cur_sub_size, part = part)
|
||||
if part == 1:
|
||||
res += sub_res
|
||||
else:
|
||||
ress.append(sub_res)
|
||||
cur_sub_size += sub_size
|
||||
i += 1
|
||||
s += tot_sub_size
|
||||
else:
|
||||
s += 11
|
||||
verbose("VVVTTTILLLLLLLLLLL")
|
||||
verbose(f"about to scan {n_subpackets(p, size)} packets")
|
||||
for _ in range(n_subpackets(p, size)):
|
||||
new_size = size - s
|
||||
mask = (1 << new_size) - 1
|
||||
new_pack = p & mask
|
||||
sub_size, sub_res = parse_packet(new_pack, size = new_size, part = part)
|
||||
s += sub_size
|
||||
if part == 1:
|
||||
res += sub_res
|
||||
else:
|
||||
ress.append(sub_res)
|
||||
|
||||
if part == 2:
|
||||
if t == 0:
|
||||
res = sum(ress)
|
||||
elif t == 1:
|
||||
res = 1
|
||||
for r in ress:
|
||||
res *= r
|
||||
elif t == 2:
|
||||
res = min(ress)
|
||||
elif t == 3:
|
||||
res = max(ress)
|
||||
elif t in [5, 6, 7]:
|
||||
if len(ress) != 2:
|
||||
raise ValueError("huston, we got a problem")
|
||||
if t == 5:
|
||||
res = int(ress[0] > ress[1])
|
||||
elif t == 6:
|
||||
res = int(ress[0] < ress[1])
|
||||
elif t == 7:
|
||||
res = int(ress[0] == ress[1])
|
||||
|
||||
|
||||
|
||||
return (s, res)
|
||||
|
||||
def result(inp, part = 1):
|
||||
return parse_packet(inp, part = part)[1]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
VERBOSE = False
|
||||
print(result(get_input(), part = 2))
|
||||
|
49
2021/16/test.py
Normal file
49
2021/16/test.py
Normal file
@ -0,0 +1,49 @@
|
||||
from prog import *
|
||||
import unittest
|
||||
|
||||
class Tests(unittest.TestCase):
|
||||
|
||||
def test_pack1(self):
|
||||
pack = 0xD2FE28
|
||||
s = full_size(pack)
|
||||
self.assertEqual(full_size(pack), 24)
|
||||
self.assertEqual(version(pack, s), 6)
|
||||
self.assertEqual(type(pack, s), 4)
|
||||
self.assertEqual(literal(pack, s), 2021)
|
||||
|
||||
def test_pack2(self):
|
||||
pack = 0x38006F45291200
|
||||
s = full_size(pack)
|
||||
self.assertEqual(full_size(pack), 56)
|
||||
self.assertEqual(version(pack, s), 1)
|
||||
self.assertEqual(type(pack, s), 6)
|
||||
self.assertEqual(type_id(pack, s), 0)
|
||||
self.assertEqual(len_subpackets(pack, s), 27)
|
||||
|
||||
def test_pack3(self):
|
||||
pack = 0xEE00D40C823060
|
||||
s = full_size(pack)
|
||||
self.assertEqual(full_size(pack), 56)
|
||||
self.assertEqual(version(pack, s), 7)
|
||||
self.assertEqual(type(pack, s), 3)
|
||||
self.assertEqual(type_id(pack, s), 1)
|
||||
self.assertEqual(n_subpackets(pack, s), 3)
|
||||
|
||||
def test_part1(self):
|
||||
self.assertEqual(result(0x8A004A801A8002F478), 16)
|
||||
self.assertEqual(result(0x620080001611562C8802118E34), 12)
|
||||
self.assertEqual(result(0xC0015000016115A2E0802F182340), 23)
|
||||
self.assertEqual(result(0xA0016C880162017C3686B18A3D4780), 31)
|
||||
|
||||
def test_part2(self):
|
||||
self.assertEqual(result(0xC200B40A82, part = 2), 3)
|
||||
self.assertEqual(result(0x880086C3E88112, part = 2), 7)
|
||||
self.assertEqual(result(0xCE00C43D881120, part = 2), 9)
|
||||
self.assertEqual(result(0xD8005AC2A8F0, part = 2), 1)
|
||||
self.assertEqual(result(0xF600BC2D8F, part = 2), 0)
|
||||
self.assertEqual(result(0x9C005AC2F8F0, part = 2), 0)
|
||||
self.assertEqual(result(0x9C0141080250320F1802104A08, part = 2), 1)
|
||||
|
||||
def test_spec(self):
|
||||
self.assertEqual(result(0x04005AC33890, part = 2), 54)
|
||||
|
Reference in New Issue
Block a user