Added 2021 (python)

This commit is contained in:
Karma Riuk
2023-08-02 11:46:44 +02:00
parent 410815acf8
commit 11600f7ba9
82 changed files with 8693 additions and 0 deletions

1
2021/16/input Normal file
View File

@ -0,0 +1 @@
40541D900AEDC01A88002191FE2F45D1006A2FC2388D278D4653E3910020F2E2F3E24C007ECD7ABA6A200E6E8017F92C934CFA0E5290B569CE0F4BA5180213D963C00DC40010A87905A0900021B0D624C34600906725FFCF597491C6008C01B0004223342488A200F4378C9198401B87311A0C0803E600FC4887F14CC01C8AF16A2010021D1260DC7530042C012957193779F96AD9B36100907A00980021513E3943600043225C1A8EB2C3040043CC3B1802B400D3CA4B8D3292E37C30600B325A541D979606E384B524C06008E802515A638A73A226009CDA5D8026200D473851150401E8BF16E2ACDFB7DCD4F5C02897A5288D299D89CA6AA672AD5118804F592FC5BE8037000042217C64876000874728550D4C0149F29D00524ACCD2566795A0D880432BEAC79995C86483A6F3B9F6833397DEA03E401004F28CD894B9C48A34BC371CF7AA840155E002012E21260923DC4C248035299ECEB0AC4DFC0179B864865CF8802F9A005E264C25372ABAC8DEA706009F005C32B7FCF1BF91CADFF3C6FE4B3FB073005A6F93B633B12E0054A124BEE9C570004B245126F6E11E5C0199BDEDCE589275C10027E97BE7EF330F126DF3817354FFC82671BB5402510C803788DFA009CAFB14ECDFE57D8A766F0001A74F924AC99678864725F253FD134400F9B5D3004A46489A00A4BEAD8F7F1F7497C39A0020F357618C71648032BB004E4BBC4292EF1167274F1AA0078902262B0D4718229C8608A5226528F86008CFA6E802F275E2248C65F3610066274CEA9A86794E58AA5E5BDE73F34945E2008D27D2278EE30C489B3D20336D00C2F002DF480AC820287D8096F700288082C001DE1400C50035005AA2013E5400B10028C009600A74001EF2004F8400C92B172801F0F4C0139B8E19A8017D96A510A7E698800EAC9294A6E985783A400AE4A2945E9170

128
2021/16/prog.py Normal file
View 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
View 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)