From 5c0b7a3b097c0e8669991dd415b3aa36baf42ff2 Mon Sep 17 00:00:00 2001 From: James Griffin Date: Sat, 18 Dec 2021 18:34:45 +0000 Subject: [PATCH] Actual solution for day 16! --- README.md | 5 +- sixteen/bits.go | 110 +++++++++++++++++++++++++++++++++---- sixteen/bits_test.go | 127 ++++++++++++++++++++++++++++++++++++++++++- sixteen/main.go | 11 ++-- 4 files changed, 231 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 4d6e840..804bf4e 100644 --- a/README.md +++ b/README.md @@ -170,7 +170,6 @@ The total risk of the least risky path is 2864 ```sh $ ./aoc2021 --sixteen The solution for "sixteen" is: -sixteen part 1 answer for bits -sixteen part 2 answer for bits +The sum of the version numbers is 1012 +The output of the encoded input is 2223947372407 ``` - diff --git a/sixteen/bits.go b/sixteen/bits.go index c1e9e81..e07b8d7 100644 --- a/sixteen/bits.go +++ b/sixteen/bits.go @@ -50,6 +50,87 @@ func (p *packet) versionSum() int { return sum } +func (p *packet) sum() int { + sum := 0 + for _, p := range p.subpackets { + sum += p.value() + } + return sum +} + +func (p *packet) product() int { + product := 1 + for _, p := range p.subpackets { + product *= p.value() + } + return product +} + +func (p *packet) min() int { + min := 0 + for i, p := range p.subpackets { + if i == 0 || p.content < min { + min = p.value() + } + } + return min +} + +func (p *packet) max() int { + max := 0 + for i, p := range p.subpackets { + if i == 0 || p.content > max { + max = p.value() + } + } + return max +} + +func (p *packet) greaterThan() int { + result := 0 + if p.subpackets[0].value() > p.subpackets[1].value() { + result = 1 + } + return result +} + +func (p *packet) lessThan() int { + result := 0 + if p.subpackets[0].value() < p.subpackets[1].value() { + result = 1 + } + return result +} + +func (p *packet) equalTo() int { + result := 0 + if p.subpackets[0].value() == p.subpackets[1].value() { + result = 1 + } + return result +} + +func (p *packet) value() int { + switch p.typeID { + case 0: + return p.sum() + case 1: + return p.product() + case 2: + return p.min() + case 3: + return p.max() + case 5: + return p.greaterThan() + case 6: + return p.lessThan() + case 7: + return p.equalTo() + } + + return p.content +} + func hexToBinary(input string) string { output := "" for _, r := range input { @@ -124,7 +205,11 @@ func parsePackets(input string) []packet { default: l := 0 p.subpackets, l = parseOperator(remaining[6:]) - remaining = remaining[l+7:] + if len(remaining) == l+6 { + remaining = "" + } else { + remaining = remaining[l+6:] + } } packets = append(packets, p) @@ -146,16 +231,21 @@ func parseNPackets(input string, count int) ([]packet, int) { typeID: typeID, } + parsedLength := 0 switch p.typeID { case literalType: - value, length := parseLiteral(remaining[6:]) + value := 0 + value, parsedLength = parseLiteral(remaining[6:]) p.content = value - p.packet = remaining[:length+6] - remaining = remaining[length+6:] + p.packet = remaining[:parsedLength+6] default: - l := 0 - p.subpackets, l = parseOperator(remaining[6:]) - remaining = remaining[l+7:] + p.subpackets, parsedLength = parseOperator(remaining[6:]) + } + + if len(remaining) == parsedLength+6 { + remaining = "" + } else { + remaining = remaining[parsedLength+6:] } packets = append(packets, p) @@ -165,7 +255,7 @@ func parseNPackets(input string, count int) ([]packet, int) { } func parseOperator(input string) ([]packet, int) { - length := 0 + length := 1 subPackets := []packet{} var lType int var remainder string @@ -179,12 +269,12 @@ func parseOperator(input string) ([]packet, int) { lengthBits, _ := strconv.ParseInt(string(remainder[:15]), 2, 64) subs := parsePackets(remainder[15 : 15+lengthBits]) subPackets = append(subPackets, subs...) - length = 15 + int(lengthBits) + length += 15 + int(lengthBits) case lengthType11: lengthBits, _ := strconv.ParseInt(string(remainder[:11]), 2, 64) subs, l := parseNPackets(remainder[11:], int(lengthBits)) subPackets = append(subPackets, subs...) - length = l + length += 11 + l } return subPackets, length diff --git a/sixteen/bits_test.go b/sixteen/bits_test.go index c8390ca..6404f23 100644 --- a/sixteen/bits_test.go +++ b/sixteen/bits_test.go @@ -1,6 +1,9 @@ package sixteen -import "testing" +import ( + "fmt" + "testing" +) func Test_hex(t *testing.T) { original := "8A004A801A8002F478" @@ -50,7 +53,7 @@ func Test_hex4(t *testing.T) { if vSum != expected { t.Logf("Expected %d, found %d", expected, vSum) - // t.Fail() + t.Fail() } } @@ -126,7 +129,7 @@ func Test_operator2(t *testing.T) { } if b.subpackets[1].content != 2 { - t.Logf("Expected second packet to be 2, found %d", b.subpackets[2].content) + t.Logf("Expected second packet to be 2, found %d", b.subpackets[2].content) t.Fail() } @@ -135,3 +138,121 @@ func Test_operator2(t *testing.T) { t.Fail() } } + +func Test_sum(t *testing.T) { + original := "C200B40A82" + expected := 3 + + p := parseHex(original) + fmt.Println(p) + v := p.value() + + if v != expected { + t.Logf("Expected %d, found %d", expected, v) + t.Fail() + } +} + +func Test_product(t *testing.T) { + original := "04005AC33890" + expected := 54 + + p := parseHex(original) + v := p.value() + + if v != expected { + t.Logf("Expected %d, found %d", expected, v) + t.Fail() + } +} + +func Test_min(t *testing.T) { + original := "880086C3E88112" + expected := 7 + + p := parseHex(original) + v := p.value() + + if v != expected { + t.Logf("Expected %d, found %d", expected, v) + t.Fail() + } +} + +func Test_max(t *testing.T) { + original := "CE00C43D881120" + expected := 9 + + p := parseHex(original) + v := p.value() + + if v != expected { + t.Logf("Expected %d, found %d", expected, v) + t.Fail() + } +} + +func Test_less(t *testing.T) { + original := "D8005AC2A8F0" + expected := 1 + + p := parseHex(original) + v := p.value() + + if v != expected { + t.Logf("Expected %d, found %d", expected, v) + t.Fail() + } +} + +func Test_more(t *testing.T) { + original := "F600BC2D8F" + expected := 0 + + p := parseHex(original) + v := p.value() + + if v != expected { + t.Logf("Expected %d, found %d", expected, v) + t.Fail() + } +} + +func Test_equal(t *testing.T) { + original := "9C005AC2F8F0" + expected := 0 + + p := parseHex(original) + v := p.value() + + if v != expected { + t.Logf("Expected %d, found %d", expected, v) + t.Fail() + } +} + +func Test_combo(t *testing.T) { + original := "9C0141080250320F1802104A08" + expected := 1 + + p := parseHex(original) + v := p.value() + + if v != expected { + t.Logf("Expected %d, found %d", expected, v) + t.Fail() + } +} + +func Test_input(t *testing.T) { + expected := 531986792411 + + p := load("input.txt") + + v := p.value() + + if v == expected { + t.Logf("Expected to not get %d, got %d", expected, v) + t.Fail() + } +} \ No newline at end of file diff --git a/sixteen/main.go b/sixteen/main.go index 8bb5ce7..9507b64 100644 --- a/sixteen/main.go +++ b/sixteen/main.go @@ -3,23 +3,22 @@ package sixteen import "fmt" type Sixteen struct { - bits packet + packet packet } func Init(filepath string) *Sixteen { sixteen := &Sixteen{ - bits: packet{}, + packet: packet{}, } - sixteen.bits = load(filepath) + sixteen.packet = load(filepath) return sixteen } func (d *Sixteen) Answer() string { - return fmt.Sprintf("The sum of the version numbers is %d", d.bits.versionSum()) + return fmt.Sprintf("The sum of the version numbers is %d", d.packet.versionSum()) } func (d *Sixteen) FollowUp() string { - return "sixteen part 2 answer for bits" + return fmt.Sprintf("The output of the encoded input is %d", d.packet.value()) } -