183 lines
3.7 KiB
Go
183 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"AoC/2021/common"
|
|
"bufio"
|
|
"encoding/hex"
|
|
)
|
|
|
|
// Also implements a special operator -1, this operator will sum the versions of all (sub)packages
|
|
func parsePackage(data []int, offset int, operator int, numberOfPackets int, lengthOfPackets int) (int, int) {
|
|
total := 0
|
|
// If we are going to multiply we need to start with 1
|
|
if operator == 1 {
|
|
total = 1
|
|
}
|
|
|
|
start := offset
|
|
for packetNumber := 0; (packetNumber < numberOfPackets || lengthOfPackets > offset - start); packetNumber++ {
|
|
version := 0
|
|
for i := 0; i < 3; i++ {
|
|
version <<= 1
|
|
version += data[offset + i]
|
|
}
|
|
offset += 3
|
|
|
|
typeID := 0
|
|
for i := 0; i < 3; i++ {
|
|
typeID <<= 1
|
|
typeID += data[offset + i]
|
|
}
|
|
offset += 3
|
|
|
|
value := 0
|
|
if typeID == 4 {
|
|
done := false
|
|
for !done {
|
|
done = data[offset + 0] == 0
|
|
offset++
|
|
for i := 0; i < 4; i++ {
|
|
value <<= 1
|
|
value += data[offset + i]
|
|
}
|
|
offset += 4
|
|
}
|
|
|
|
if operator == -1 {
|
|
value = version
|
|
}
|
|
} else {
|
|
lengthTypeID := data[offset + 0]
|
|
offset++
|
|
|
|
lop := 0
|
|
nop := 0
|
|
if lengthTypeID == 0 {
|
|
for i := 0; i < 15; i++ {
|
|
lop <<= 1
|
|
lop += data[offset + i]
|
|
}
|
|
offset += 15
|
|
} else if lengthTypeID == 1 {
|
|
for i := 0; i < 11; i++ {
|
|
nop <<= 1
|
|
nop += data[offset + i]
|
|
}
|
|
offset += 11
|
|
} else {
|
|
panic("Unknown lengthTypeID")
|
|
}
|
|
|
|
if operator == -1 {
|
|
typeID = -1
|
|
}
|
|
|
|
offset, value = parsePackage(data, offset, typeID, nop, lop)
|
|
|
|
if operator == -1 {
|
|
value += version
|
|
}
|
|
}
|
|
|
|
switch operator {
|
|
case -1, 0:
|
|
total += value
|
|
case 1:
|
|
total *= value
|
|
case 2:
|
|
if value < total || packetNumber == 0 {
|
|
total = value
|
|
}
|
|
case 3:
|
|
if value > total || packetNumber == 0 {
|
|
total = value
|
|
}
|
|
case 5:
|
|
if packetNumber == 0 {
|
|
total = value
|
|
} else if packetNumber == 1 {
|
|
if total > value {
|
|
total = 1
|
|
} else {
|
|
total = 0
|
|
}
|
|
} else {
|
|
panic("To many sub packets for 'greater than' operator")
|
|
}
|
|
case 6:
|
|
if packetNumber == 0 {
|
|
total = value
|
|
} else if packetNumber == 1 {
|
|
if total < value {
|
|
total = 1
|
|
} else {
|
|
total = 0
|
|
}
|
|
} else {
|
|
panic("To many sub packets for 'less than' operator")
|
|
}
|
|
case 7:
|
|
if packetNumber == 0 {
|
|
total = value
|
|
} else if packetNumber == 1 {
|
|
if total == value {
|
|
total = 1
|
|
} else {
|
|
total = 0
|
|
}
|
|
} else {
|
|
panic("To many sub packets for 'equal to' operator")
|
|
}
|
|
}
|
|
}
|
|
|
|
return offset, total
|
|
}
|
|
|
|
func parseInput(input *bufio.Scanner) []int {
|
|
input.Scan()
|
|
in, _ := hex.DecodeString(input.Text())
|
|
|
|
var data []int
|
|
for _, b := range in {
|
|
for i := 7; i >= 0; i-- {
|
|
data = append(data, int((b >> i) & 1))
|
|
}
|
|
}
|
|
|
|
return data
|
|
}
|
|
|
|
func main() {
|
|
challenge := aoc.New(2021, 16)
|
|
|
|
challenge.Test(`D2FE28`, []int{6, -2})
|
|
challenge.Test(`8A004A801A8002F478`, []int{16, -2})
|
|
challenge.Test(`620080001611562C8802118E34`, []int{12, -2})
|
|
challenge.Test(`C0015000016115A2E0802F182340`, []int{23, -2})
|
|
challenge.Test(`A0016C880162017C3686B18A3D4780`, []int{31, -2})
|
|
|
|
challenge.Test(`C200B40A82`, []int{-2, 3})
|
|
challenge.Test(`04005AC33890`, []int{-2, 54})
|
|
challenge.Test(`880086C3E88112`, []int{-2, 7})
|
|
challenge.Test(`CE00C43D881120`, []int{-2, 9})
|
|
challenge.Test(`D8005AC2A8F0`, []int{-2, 1})
|
|
challenge.Test(`F600BC2D8F`, []int{-2, 0})
|
|
challenge.Test(`9C005AC2F8F0`, []int{-2, 0})
|
|
challenge.Test(`9C0141080250320F1802104A08`, []int{-2, 1})
|
|
|
|
challenge.Solution(1, func (input *bufio.Scanner) int {
|
|
data := parseInput(input)
|
|
_, sum := parsePackage(data, 0, -1, 1, 0)
|
|
|
|
return sum
|
|
})
|
|
|
|
challenge.Solution(2, func (input *bufio.Scanner) int {
|
|
data := parseInput(input)
|
|
_, sum := parsePackage(data, 0, 0, 1, 0)
|
|
|
|
return sum
|
|
})
|
|
}
|