diff --git a/16/main.go b/16/main.go index 4e93851..a91ca6d 100644 --- a/16/main.go +++ b/16/main.go @@ -111,12 +111,15 @@ func parsePackets(stream []uint8) (int, packet) { size, subpacketlength := getSubpacketLength(stream[6], stream[7:]) for { consumed, subs := parsePackets(stream[7+size+parsed:]) + if consumed == 0 { + return parsed + 7 + size, parsedPacket + } parsedPacket.subPackets = append(parsedPacket.subPackets, subs) parsed += consumed if size == 11 && len(parsedPacket.subPackets) == subpacketlength { return parsed + 7 + size, parsedPacket - } else if size == 15 && parsed > subpacketlength || consumed == 0 { + } else if size == 15 && parsed > subpacketlength { return parsed + 7 + size, parsedPacket } } @@ -144,10 +147,97 @@ func partOne() { fmt.Println(countVersions(parsedPacket)) } +func solve(p packet) int { + switch p.typeID { + case 0: // sum + if len(p.subPackets) == 1 { + return solve(p.subPackets[0]) + } else { + acc := 0 + for _, v := range p.subPackets { + acc += solve(v) + } + return acc + } + case 1: // product + if len(p.subPackets) == 1 { + return solve(p.subPackets[0]) + } else { + acc := solve(p.subPackets[0]) + for _, v := range p.subPackets[1:] { + acc *= solve(v) + } + return acc + } + case 2: // min + if len(p.subPackets) == 1 { + return solve(p.subPackets[0]) + } else { + acc := solve(p.subPackets[0]) + for _, v := range p.subPackets[1:] { + t := solve(v) + if t < acc { + acc = t + } + } + return acc + } + case 3: // max + if len(p.subPackets) == 1 { + return solve(p.subPackets[0]) + } else { + acc := solve(p.subPackets[0]) + for _, v := range p.subPackets[1:] { + t := solve(v) + if t > acc { + acc = t + } + } + return acc + } + case 4: // number + return p.encodedNumber + case 5: // > + if len(p.subPackets) != 2 { + panic(fmt.Sprintf("recevied type 5 packet with %d subpackets", len(p.subPackets))) + } + if solve(p.subPackets[0]) > solve(p.subPackets[1]) { + return 1 + } else { + return 0 + } + case 6: // < + if len(p.subPackets) != 2 { + panic(fmt.Sprintf("recevied type 6 packet with %d subpackets", len(p.subPackets))) + } + if solve(p.subPackets[0]) < solve(p.subPackets[1]) { + return 1 + } else { + return 0 + } + case 7: // == + if len(p.subPackets) != 2 { + panic(fmt.Sprintf("recevied type 7 packet with %d subpackets", len(p.subPackets))) + } + if solve(p.subPackets[0]) == solve(p.subPackets[1]) { + return 1 + } else { + return 0 + } + default: + panic("unknown packet type") + } +} + func partTwo() { scanner := makeScanner(false) - for scanner.Scan() { - // line := scanner.Text() + scanner.Scan() + line := scanner.Text() + stream := []uint8{} + for _, hex := range line { + stream = append(stream, hexMap[hex]...) } + _, parsedPacket := parsePackets(stream) + fmt.Println(solve(parsedPacket)) } diff --git a/16/main_test.go b/16/main_test.go index c9de669..6470057 100644 --- a/16/main_test.go +++ b/16/main_test.go @@ -59,3 +59,28 @@ func TestCases(t *testing.T) { } } } + +func TestSolving(t *testing.T) { + inputs := map[string]int{ + "C200B40A82": 3, + "04005AC33890": 54, + "880086C3E88112": 7, + "CE00C43D881120": 9, + "D8005AC2A8F0": 1, + "F600BC2D8F": 0, + "9C005AC2F8F0": 0, + "9C0141080250320F1802104A08": 1, + } + + for c, r := range inputs { + stream := []uint8{} + for _, hex := range c { + stream = append(stream, hexMap[hex]...) + } + _, parsedPacket := parsePackets(stream) + if r != solve(parsedPacket) { + t.Log(c, solve(parsedPacket)) + t.Fail() + } + } +}