diff --git a/AoC2021/challenges/challenge16 b/AoC2021/challenges/challenge16 new file mode 100644 index 0000000..6c425fd --- /dev/null +++ b/AoC2021/challenges/challenge16 @@ -0,0 +1,127 @@ +--- Day 16: Packet Decoder --- + +As you leave the cave and reach open waters, you receive a transmission from the Elves back on the ship. + +The transmission was sent using the Buoyancy Interchange Transmission System (BITS), a method of packing numeric expressions into a binary sequence. Your submarine's computer has saved the transmission in hexadecimal (your puzzle input). + +The first step of decoding the message is to convert the hexadecimal representation into binary. Each character of hexadecimal corresponds to four bits of binary data: + +0 = 0000 +1 = 0001 +2 = 0010 +3 = 0011 +4 = 0100 +5 = 0101 +6 = 0110 +7 = 0111 +8 = 1000 +9 = 1001 +A = 1010 +B = 1011 +C = 1100 +D = 1101 +E = 1110 +F = 1111 + +The BITS transmission contains a single packet at its outermost layer which itself contains many other packets. The hexadecimal representation of this packet might encode a few extra 0 bits at the end; these are not part of the transmission and should be ignored. + +Every packet begins with a standard header: the first three bits encode the packet version, and the next three bits encode the packet type ID. These two values are numbers; all numbers encoded in any packet are represented as binary with the most significant bit first. For example, a version encoded as the binary sequence 100 represents the number 4. + +Packets with type ID 4 represent a literal value. Literal value packets encode a single binary number. To do this, the binary number is padded with leading zeroes until its length is a multiple of four bits, and then it is broken into groups of four bits. Each group is prefixed by a 1 bit except the last group, which is prefixed by a 0 bit. These groups of five bits immediately follow the packet header. For example, the hexadecimal string D2FE28 becomes: + +110100101111111000101000 +VVVTTTAAAAABBBBBCCCCC + +Below each bit is a label indicating its purpose: + + The three bits labeled V (110) are the packet version, 6. + The three bits labeled T (100) are the packet type ID, 4, which means the packet is a literal value. + The five bits labeled A (10111) start with a 1 (not the last group, keep reading) and contain the first four bits of the number, 0111. + The five bits labeled B (11110) start with a 1 (not the last group, keep reading) and contain four more bits of the number, 1110. + The five bits labeled C (00101) start with a 0 (last group, end of packet) and contain the last four bits of the number, 0101. + The three unlabeled 0 bits at the end are extra due to the hexadecimal representation and should be ignored. + +So, this packet represents a literal value with binary representation 011111100101, which is 2021 in decimal. + +Every other type of packet (any packet with a type ID other than 4) represent an operator that performs some calculation on one or more sub-packets contained within. Right now, the specific operations aren't important; focus on parsing the hierarchy of sub-packets. + +An operator packet contains one or more packets. To indicate which subsequent binary data represents its sub-packets, an operator packet can use one of two modes indicated by the bit immediately after the packet header; this is called the length type ID: + + If the length type ID is 0, then the next 15 bits are a number that represents the total length in bits of the sub-packets contained by this packet. + If the length type ID is 1, then the next 11 bits are a number that represents the number of sub-packets immediately contained by this packet. + +Finally, after the length type ID bit and the 15-bit or 11-bit field, the sub-packets appear. + +For example, here is an operator packet (hexadecimal string 38006F45291200) with length type ID 0 that contains two sub-packets: + +00111000000000000110111101000101001010010001001000000000 +VVVTTTILLLLLLLLLLLLLLLAAAAAAAAAAABBBBBBBBBBBBBBBB + + The three bits labeled V (001) are the packet version, 1. + The three bits labeled T (110) are the packet type ID, 6, which means the packet is an operator. + The bit labeled I (0) is the length type ID, which indicates that the length is a 15-bit number representing the number of bits in the sub-packets. + The 15 bits labeled L (000000000011011) contain the length of the sub-packets in bits, 27. + The 11 bits labeled A contain the first sub-packet, a literal value representing the number 10. + The 16 bits labeled B contain the second sub-packet, a literal value representing the number 20. + +After reading 11 and 16 bits of sub-packet data, the total length indicated in L (27) is reached, and so parsing of this packet stops. + +As another example, here is an operator packet (hexadecimal string EE00D40C823060) with length type ID 1 that contains three sub-packets: + +11101110000000001101010000001100100000100011000001100000 +VVVTTTILLLLLLLLLLLAAAAAAAAAAABBBBBBBBBBBCCCCCCCCCCC + + The three bits labeled V (111) are the packet version, 7. + The three bits labeled T (011) are the packet type ID, 3, which means the packet is an operator. + The bit labeled I (1) is the length type ID, which indicates that the length is a 11-bit number representing the number of sub-packets. + The 11 bits labeled L (00000000011) contain the number of sub-packets, 3. + The 11 bits labeled A contain the first sub-packet, a literal value representing the number 1. + The 11 bits labeled B contain the second sub-packet, a literal value representing the number 2. + The 11 bits labeled C contain the third sub-packet, a literal value representing the number 3. + +After reading 3 complete sub-packets, the number of sub-packets indicated in L (3) is reached, and so parsing of this packet stops. + +For now, parse the hierarchy of the packets throughout the transmission and add up all of the version numbers. + +Here are a few more examples of hexadecimal-encoded transmissions: + + 8A004A801A8002F478 represents an operator packet (version 4) which contains an operator packet (version 1) which contains an operator packet (version 5) which contains a literal value (version 6); this packet has a version sum of 16. + 620080001611562C8802118E34 represents an operator packet (version 3) which contains two sub-packets; each sub-packet is an operator packet that contains two literal values. This packet has a version sum of 12. + C0015000016115A2E0802F182340 has the same structure as the previous example, but the outermost packet uses a different length type ID. This packet has a version sum of 23. + A0016C880162017C3686B18A3D4780 is an operator packet that contains an operator packet that contains an operator packet that contains five literal values; it has a version sum of 31. + +Decode the structure of your hexadecimal-encoded BITS transmission; what do you get if you add up the version numbers in all packets? + +Your puzzle answer was 971. +--- Part Two --- + +Now that you have the structure of your transmission decoded, you can calculate the value of the expression it represents. + +Literal values (type ID 4) represent a single number as described above. The remaining type IDs are more interesting: + + Packets with type ID 0 are sum packets - their value is the sum of the values of their sub-packets. If they only have a single sub-packet, their value is the value of the sub-packet. + Packets with type ID 1 are product packets - their value is the result of multiplying together the values of their sub-packets. If they only have a single sub-packet, their value is the value of the sub-packet. + Packets with type ID 2 are minimum packets - their value is the minimum of the values of their sub-packets. + Packets with type ID 3 are maximum packets - their value is the maximum of the values of their sub-packets. + Packets with type ID 5 are greater than packets - their value is 1 if the value of the first sub-packet is greater than the value of the second sub-packet; otherwise, their value is 0. These packets always have exactly two sub-packets. + Packets with type ID 6 are less than packets - their value is 1 if the value of the first sub-packet is less than the value of the second sub-packet; otherwise, their value is 0. These packets always have exactly two sub-packets. + Packets with type ID 7 are equal to packets - their value is 1 if the value of the first sub-packet is equal to the value of the second sub-packet; otherwise, their value is 0. These packets always have exactly two sub-packets. + +Using these rules, you can now work out the value of the outermost packet in your BITS transmission. + +For example: + + C200B40A82 finds the sum of 1 and 2, resulting in the value 3. + 04005AC33890 finds the product of 6 and 9, resulting in the value 54. + 880086C3E88112 finds the minimum of 7, 8, and 9, resulting in the value 7. + CE00C43D881120 finds the maximum of 7, 8, and 9, resulting in the value 9. + D8005AC2A8F0 produces 1, because 5 is less than 15. + F600BC2D8F produces 0, because 5 is not greater than 15. + 9C005AC2F8F0 produces 0, because 5 is not equal to 15. + 9C0141080250320F1802104A08 produces 1, because 1 + 3 = 2 * 2. + +What do you get if you evaluate the expression represented by your hexadecimal-encoded BITS transmission? + +Your puzzle answer was 831996589851. + +Both parts of this puzzle are complete! They provide two gold stars: ** diff --git a/AoC2021/AoC16.py b/AoC2021/code/AoC16.py similarity index 65% rename from AoC2021/AoC16.py rename to AoC2021/code/AoC16.py index 716a2f8..e351bda 100755 --- a/AoC2021/AoC16.py +++ b/AoC2021/code/AoC16.py @@ -2,22 +2,21 @@ import sys from bitstring import BitArray - +from operator import mul +from functools import reduce def parse_packet(packet, s, np=100000000, length=1000000000): - print(s, np, length) nex = s end = s+length-1 bv = 0 + numbers = [] while np > 0 and nex < min(len(packet)+1,end): if (len(packet[nex:end+1]) == 0 or int(''.join(packet[nex:end+1]),2) == 0 or int(''.join(packet[nex:]),2) == 0): - if length < 1000000000: - nex = end+1 + if length < 1000000000: nex = end+1 break v = int(''.join(packet[nex:nex+3]),2) bv += v t = int(''.join(packet[nex+3:nex+6]),2) - print(v,t) nex += 6 if t == 4: num = [] @@ -27,37 +26,43 @@ def parse_packet(packet, s, np=100000000, length=1000000000): num.append(list(packet[nex+1:nex+5])) nex += 5 i = int(''.join([''.join(n) for n in num]),2) - print("num: " + str(i)) - nex += (nex-s+1) % 4 - s = nex + numbers.append(i) else: I = packet[nex] nex += 1 if I == '1': l = int(''.join(packet[nex:nex+11]),2) nex += 11 - b, nex = parse_packet(packet, nex, np=l) + b, nex, numbs = parse_packet(packet, nex, np=l) bv += b elif I == '0': l = int(''.join(packet[nex:nex+15]),2) nex += 15 - b, nex = parse_packet(packet, nex, length=l) + b, nex, numbs = parse_packet(packet, nex, length=l) bv += b + if t == 0: numbers.append(sum(numbs)) + elif t == 1: numbers.append(reduce(mul, numbs, 1)) + elif t == 2: numbers.append(min(numbs)) + elif t == 3: numbers.append(max(numbs)) + elif t == 5: numbers.append(int(numbs[0] > numbs[1])) + elif t == 6: numbers.append(int(numbs[0] < numbs[1])) + elif t == 7: numbers.append(int(numbs[0] == numbs[1])) + np -= 1 - return bv, nex + return bv, nex, numbers if __name__ == '__main__': hexa = [list(line.strip('\n')) for line in open(sys.argv[1])] bits = [list(BitArray(hex=c).bin) for c in hexa[0]] bits = [b for l in bits for b in l] - print(bits, len(bits)) - bv = parse_packet(bits,0,np=1) + bv, _, num = parse_packet(bits,0,np=1) + # challenge 1 res1 = str(bv) print("challenge 1:" + "\n" + res1 + "\n") # challenge 2 - res2 = "" + res2 = str(num[0]) print("challenge 2:" + "\n" + res2 + "\n") diff --git a/AoC2021/inputs/input16 b/AoC2021/inputs/input16 new file mode 100644 index 0000000..8650b4e --- /dev/null +++ b/AoC2021/inputs/input16 @@ -0,0 +1 @@ +805311100469800804A3E488ACC0B10055D8009548874F65665AD42F60073E7338E7E5C538D820114AEA1A19927797976F8F43CD7354D66747B3005B401397C6CBA2FCEEE7AACDECC017938B3F802E000854488F70FC401F8BD09E199005B3600BCBFEEE12FFBB84FC8466B515E92B79B1003C797AEBAF53917E99FF2E953D0D284359CA0CB80193D12B3005B4017968D77EB224B46BBF591E7BEBD2FA00100622B4ED64773D0CF7816600B68020000874718E715C0010D8AF1E61CC946FB99FC2C20098275EBC0109FA14CAEDC20EB8033389531AAB14C72162492DE33AE0118012C05EEB801C0054F880102007A01192C040E100ED20035DA8018402BE20099A0020CB801AE0049801E800DD10021E4002DC7D30046C0160004323E42C8EA200DC5A87D06250C50015097FB2CFC93A101006F532EB600849634912799EF7BF609270D0802B59876F004246941091A5040402C9BD4DF654967BFDE4A6432769CED4EC3C4F04C000A895B8E98013246A6016CB3CCC94C9144A03CFAB9002033E7B24A24016DD802933AFAE48EAA3335A632013BC401D8850863A8803D1C61447A00042E3647B83F313674009E6533E158C3351F94C9902803D35C869865D564690103004E74CB001F39BEFFAAD37DFF558C012D005A5A9E851D25F76DD88A5F4BC600ACB6E1322B004E5FE1F2FF0E3005EC017969EB7AE4D1A53D07B918C0B1802F088B2C810326215CCBB6BC140C0149EE87780233E0D298C33B008C52763C9C94BF8DC886504E1ECD4E75C7E4EA00284180371362C44320043E2EC258F24008747785D10C001039F80644F201217401500043A2244B8D200085C3F8690BA78F08018394079A7A996D200806647A49E249C675C0802609D66B004658BA7F1562500366279CCBEB2600ACCA6D802C00085C658BD1DC401A8EB136100