From e91157fca78b785cb3ede3d966a60c68c4214338 Mon Sep 17 00:00:00 2001 From: Brian Buller Date: Thu, 16 Dec 2021 10:02:14 -0600 Subject: [PATCH] 2021 Day 16 Complete --- 2021/day16/input | 1 + 2021/day16/main.go | 240 ++++++++++++++++++++++++++++ 2021/day16/packet_literal2021 | 1 + 2021/day16/packet_literal2021_cruft | 1 + 2021/day16/packet_operator0 | 1 + 2021/day16/packet_operator0_cruft | 1 + 2021/day16/packet_operator1 | 1 + 2021/day16/test.json | 1 + 2021/day16/testinput1 | 1 + 2021/day16/testinput2 | 1 + 2021/day16/testinput3 | 1 + 2021/day16/testinput4 | 1 + 12 files changed, 251 insertions(+) create mode 100644 2021/day16/input create mode 100644 2021/day16/main.go create mode 100644 2021/day16/packet_literal2021 create mode 100644 2021/day16/packet_literal2021_cruft create mode 100644 2021/day16/packet_operator0 create mode 100644 2021/day16/packet_operator0_cruft create mode 100644 2021/day16/packet_operator1 create mode 100644 2021/day16/test.json create mode 100644 2021/day16/testinput1 create mode 100644 2021/day16/testinput2 create mode 100644 2021/day16/testinput3 create mode 100644 2021/day16/testinput4 diff --git a/2021/day16/input b/2021/day16/input new file mode 100644 index 0000000..b60e296 --- /dev/null +++ b/2021/day16/input @@ -0,0 +1 @@ +E0529D18025800ABCA6996534CB22E4C00FB48E233BAEC947A8AA010CE1249DB51A02CC7DB67EF33D4002AE6ACDC40101CF0449AE4D9E4C071802D400F84BD21CAF3C8F2C35295EF3E0A600848F77893360066C200F476841040401C88908A19B001FD35CCF0B40012992AC81E3B980553659366736653A931018027C87332011E2771FFC3CEEC0630A80126007B0152E2005280186004101060C03C0200DA66006B8018200538012C01F3300660401433801A6007380132DD993100A4DC01AB0803B1FE2343500042E24C338B33F5852C3E002749803B0422EC782004221A41A8CE600EC2F8F11FD0037196CF19A67AA926892D2C643675A0C013C00CC0401F82F1BA168803510E3942E969C389C40193CFD27C32E005F271CE4B95906C151003A7BD229300362D1802727056C00556769101921F200AC74015960E97EC3F2D03C2430046C0119A3E9A3F95FD3AFE40132CEC52F4017995D9993A90060729EFCA52D3168021223F2236600ECC874E10CC1F9802F3A71C00964EC46E6580402291FE59E0FCF2B4EC31C9C7A6860094B2C4D2E880592F1AD7782992D204A82C954EA5A52E8030064D02A6C1E4EA852FE83D49CB4AE4020CD80272D3B4AA552D3B4AA5B356F77BF1630056C0119FF16C5192901CEDFB77A200E9E65EAC01693C0BCA76FEBE73487CC64DEC804659274A00CDC401F8B51CE3F8803B05217C2E40041A72E2516A663F119AC72250A00F44A98893C453005E57415A00BCD5F1DD66F3448D2600AC66F005246500C9194039C01986B317CDB10890C94BF68E6DF950C0802B09496E8A3600BCB15CA44425279539B089EB7774DDA33642012DA6B1E15B005C0010C8C917A2B880391160944D30074401D845172180803D1AA3045F00042630C5B866200CC2A9A5091C43BBD964D7F5D8914B46F040 diff --git a/2021/day16/main.go b/2021/day16/main.go new file mode 100644 index 0000000..ed90a3e --- /dev/null +++ b/2021/day16/main.go @@ -0,0 +1,240 @@ +package main + +import ( + "fmt" + "os" + + h "git.bullercodeworks.com/brian/adventofcode/helpers" +) + +func main() { + inp := h.StdinToString() + var arg string + if len(os.Args) > 1 { + arg = os.Args[1] + } + + p := ParsePacket(inp) + if arg == "--json" { + fmt.Println(p.Json()) + } else { + fmt.Println("# Part 1") + fmt.Println("Version Sum:", CalculateVersionSum(p)) + fmt.Println() + fmt.Println("# Part 2") + fmt.Println("Value:", p.value) + } +} + +func CalculateVersionSum(p *Packet) int { + sum := p.version + for s := range p.packets { + sum += CalculateVersionSum(p.packets[s]) + } + return sum +} + +const ( + PacketTypeSum = iota + PacketTypeProduct + PacketTypeMin + PacketTypeMax + PacketTypeLiteral + PacketTypeGreater + PacketTypeLess + PacketTypeEqual + + LengthTypeBits = 0 + LengthTypeSubPackets = 1 +) + +type Packet struct { + version int + packetType int + + value int + + // Operator + lengthTypeId int + subLength int + + // Sub-packets + packets []*Packet + + binaryString string +} + +func ParsePacket(inp string) *Packet { + var bin string + for i := 0; i < len(inp); i += 2 { + if len(inp) >= i+2 { + bin += fmt.Sprintf("%08b", HexToByte(inp[i:i+2])) + } + } + return ParseBinaryPacket(bin) +} + +func ParseBinaryPacket(inp string) *Packet { + p := Packet{ + binaryString: inp, + } + // Parse the version + for i := 0; i < 3; i++ { + p.version = p.version << 1 + if p.binaryString[i] == '1' { + p.version |= 1 + } + } + for i := 3; i < 6; i++ { + p.packetType = p.packetType << 1 + if p.binaryString[i] == '1' { + p.packetType |= 1 + } + } + if p.packetType == PacketTypeLiteral { + p.parseLiteral() + } else { + p.parseOperator() + } + return &p +} + +func (p *Packet) parseLiteral() { + // The bits for the literal start at bit 7 + // Every 5 bits is a chunk of the literal + ptr := 6 + more := true + for more { + more = (p.binaryString[ptr] == '1') + ptr++ + for i := 0; i < 4; i++ { + p.value = p.value << 1 + if p.binaryString[ptr] == '1' { + p.value |= 1 + } + ptr++ + } + } + p.binaryString = p.binaryString[:ptr] +} + +func (p *Packet) parseOperator() { + ptr := 6 + p.lengthTypeId = int(p.binaryString[ptr] - '0') + ptr++ + if p.lengthTypeId == LengthTypeBits { + for i := 0; i < 15; i++ { + p.subLength = p.subLength << 1 + if p.binaryString[ptr] == '1' { + p.subLength |= 1 + } + ptr++ + } + length := p.subLength + for length > 0 { + sp := ParseBinaryPacket(p.binaryString[ptr:]) + p.packets = append(p.packets, sp) + ptr += len(sp.binaryString) + length -= len(sp.binaryString) + } + p.binaryString = p.binaryString[:ptr] + } else if p.lengthTypeId == LengthTypeSubPackets { + for i := 0; i < 11; i++ { + p.subLength = p.subLength << 1 + if p.binaryString[ptr] == '1' { + p.subLength |= 1 + } + ptr++ + } + length := p.subLength + for length > 0 { + sp := ParseBinaryPacket(p.binaryString[ptr:]) + p.packets = append(p.packets, sp) + ptr += len(sp.binaryString) + length-- + } + p.binaryString = p.binaryString[:ptr] + } + switch p.packetType { + case PacketTypeSum: + for _, sp := range p.packets { + p.value += sp.value + } + case PacketTypeProduct: + p.value = 1 + for _, sp := range p.packets { + p.value *= sp.value + } + case PacketTypeMin: + p.value = h.MAX_INT + for _, sp := range p.packets { + if sp.value < p.value { + p.value = sp.value + } + } + case PacketTypeMax: + p.value = h.MIN_INT + for _, sp := range p.packets { + if sp.value > p.value { + p.value = sp.value + } + } + case PacketTypeGreater: + if len(p.packets) == 2 && (p.packets[0].value > p.packets[1].value) { + p.value = 1 + } else { + p.value = 0 + } + case PacketTypeLess: + if len(p.packets) == 2 && (p.packets[0].value < p.packets[1].value) { + p.value = 1 + } else { + p.value = 0 + } + case PacketTypeEqual: + if len(p.packets) == 2 && (p.packets[0].value == p.packets[1].value) { + p.value = 1 + } else { + p.value = 0 + } + } +} + +func (p Packet) Json() string { + ret := fmt.Sprintf("{\"version\":%d, \"type\":%d, \"value\":%d,", p.version, p.packetType, p.value) + ret += "\"packets\":[" + for i := range p.packets { + ret += fmt.Sprintf("%s", p.packets[i].String()) + if i < len(p.packets)-1 { + ret += "," + } + } + ret += fmt.Sprintf("],\"binary\":\"%s\"}", p.binaryString) + return ret +} + +func (p Packet) String() string { + if p.packetType == PacketTypeLiteral { + return fmt.Sprintf("%d", p.value) + } else { + return p.Json() + } +} + +func HexToByte(h string) byte { + var b byte + for i := range h { + var wrk byte + if h[i] >= '0' && h[i] <= '9' { + wrk = byte(h[i] - '0') + } else if h[i] >= 'A' && h[i] <= 'F' { + wrk = byte(h[i]-'A') + 10 + } + if i == 0 { + b = wrk << 4 + } else { + b |= wrk + } + } + return b +} diff --git a/2021/day16/packet_literal2021 b/2021/day16/packet_literal2021 new file mode 100644 index 0000000..3f0eda1 --- /dev/null +++ b/2021/day16/packet_literal2021 @@ -0,0 +1 @@ +D2FE28 diff --git a/2021/day16/packet_literal2021_cruft b/2021/day16/packet_literal2021_cruft new file mode 100644 index 0000000..13d6160 --- /dev/null +++ b/2021/day16/packet_literal2021_cruft @@ -0,0 +1 @@ +D2FE28FEDCBA987654321 diff --git a/2021/day16/packet_operator0 b/2021/day16/packet_operator0 new file mode 100644 index 0000000..a7f8f25 --- /dev/null +++ b/2021/day16/packet_operator0 @@ -0,0 +1 @@ +38006F45291200 diff --git a/2021/day16/packet_operator0_cruft b/2021/day16/packet_operator0_cruft new file mode 100644 index 0000000..93a5ff8 --- /dev/null +++ b/2021/day16/packet_operator0_cruft @@ -0,0 +1 @@ +38006F45291200FEDCBA0987654321 diff --git a/2021/day16/packet_operator1 b/2021/day16/packet_operator1 new file mode 100644 index 0000000..bcc798c --- /dev/null +++ b/2021/day16/packet_operator1 @@ -0,0 +1 @@ +EE00D40C823060 diff --git a/2021/day16/test.json b/2021/day16/test.json new file mode 100644 index 0000000..6f412f5 --- /dev/null +++ b/2021/day16/test.json @@ -0,0 +1 @@ +{"version":0, "type":1, "binary":"00000100000000000101101011000011001110001001",'packets':[6,9]} diff --git a/2021/day16/testinput1 b/2021/day16/testinput1 new file mode 100644 index 0000000..0d2cbff --- /dev/null +++ b/2021/day16/testinput1 @@ -0,0 +1 @@ +8A004A801A8002F478 diff --git a/2021/day16/testinput2 b/2021/day16/testinput2 new file mode 100644 index 0000000..ed3b78a --- /dev/null +++ b/2021/day16/testinput2 @@ -0,0 +1 @@ +620080001611562C8802118E34 diff --git a/2021/day16/testinput3 b/2021/day16/testinput3 new file mode 100644 index 0000000..827e51b --- /dev/null +++ b/2021/day16/testinput3 @@ -0,0 +1 @@ +C0015000016115A2E0802F182340 diff --git a/2021/day16/testinput4 b/2021/day16/testinput4 new file mode 100644 index 0000000..0a1278e --- /dev/null +++ b/2021/day16/testinput4 @@ -0,0 +1 @@ +A0016C880162017C3686B18A3D4780