Day 16 first attempt. Not working yet

This commit is contained in:
2021-12-17 04:03:28 +00:00
parent c8b291bcb8
commit 719c895220
6 changed files with 403 additions and 0 deletions

View File

@@ -164,3 +164,13 @@ The solution for "fifteen" is:
The total risk of the least risky path is 415
The total risk of the least risky path is 2864
```
### Day sixteen
```sh
$ ./aoc2021 --sixteen
The solution for "sixteen" is:
sixteen part 1 answer for bits
sixteen part 2 answer for bits
```

View File

@@ -15,6 +15,7 @@ import (
"unsupervised.ca/aoc2021/one"
"unsupervised.ca/aoc2021/seven"
"unsupervised.ca/aoc2021/six"
"unsupervised.ca/aoc2021/sixteen"
"unsupervised.ca/aoc2021/ten"
"unsupervised.ca/aoc2021/thirteen"
"unsupervised.ca/aoc2021/three"
@@ -67,6 +68,8 @@ func main() {
day = fourteen.Init("fourteen/input.txt")
case "fifteen":
day = fifteen.Init("fifteen/input.txt")
case "sixteen":
day = sixteen.Init("sixteen/input.txt")
default:
fmt.Printf("%q does not have a solution.\n", flagParts[1])
help()

227
sixteen/bits.go Normal file
View File

@@ -0,0 +1,227 @@
package sixteen
import (
"bufio"
"fmt"
"os"
"strconv"
)
const (
literalType = 4
lengthType15 = 0
lengthType11 = 1
)
var hexToBin = map[string]string{
"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",
}
type packet struct {
packet string
version int
typeID int
content int
subpackets []packet
}
func (p *packet) versionSum() int {
sum := p.version
for _, s := range p.subpackets {
sum += s.versionSum()
}
return sum
}
func hexToBinary(input string) string {
output := ""
for _, r := range input {
output += hexToBin[string(r)]
}
return output
}
func parseHex(input string) packet {
binary := hexToBinary(input)
return parse(binary)
}
func parse(input string) packet {
b := packet{}
b.packet = input
b.version, b.typeID = parseVersionType(input)
content := input[6:]
switch b.typeID {
case literalType:
b.content, _ = parseLiteral(content)
default:
b.subpackets, _ = parseOperator(content)
}
return b
}
func parseVersionType(input string) (int, int) {
var version, typeID string
if count, err := fmt.Sscanf(input, "%3s%3s", &version, &typeID); count != 2 || err != nil {
fmt.Println("Unable to parse", input, err)
return -1, -1
}
v, err := strconv.ParseInt(version, 2, 64)
if err != nil {
fmt.Println("Unable to parse version from", version, err)
return -1, -1
}
t, err := strconv.ParseInt(typeID, 2, 64)
if err != nil {
fmt.Println("Unable to parse type from", typeID, err)
return -1, -1
}
return int(v), int(t)
}
func parsePackets(input string) []packet {
packets := []packet{}
remaining := input
for remaining != "" {
version, typeID := parseVersionType(remaining)
p := packet{
version: version,
typeID: typeID,
}
switch p.typeID {
case literalType:
value, length := parseLiteral(remaining[6:])
p.content = value
p.packet = remaining[:length+6]
remaining = remaining[length+6:]
default:
l := 0
p.subpackets, l = parseOperator(remaining[6:])
remaining = remaining[l+7:]
}
packets = append(packets, p)
}
return packets
}
func parseNPackets(input string, count int) ([]packet, int) {
length := len(input)
packets := []packet{}
remaining := input
for len(packets) != count {
version, typeID := parseVersionType(remaining)
p := packet{
version: version,
typeID: typeID,
}
switch p.typeID {
case literalType:
value, length := parseLiteral(remaining[6:])
p.content = value
p.packet = remaining[:length+6]
remaining = remaining[length+6:]
default:
l := 0
p.subpackets, l = parseOperator(remaining[6:])
remaining = remaining[l+7:]
}
packets = append(packets, p)
}
return packets, length - len(remaining)
}
func parseOperator(input string) ([]packet, int) {
length := 0
subPackets := []packet{}
var lType int
var remainder string
if count, err := fmt.Sscanf(input, "%1d%s", &lType, &remainder); count != 2 || err != nil {
fmt.Println("Unable to parse operator type", input)
return subPackets, length
}
switch lType {
case lengthType15:
lengthBits, _ := strconv.ParseInt(string(remainder[:15]), 2, 64)
subs := parsePackets(remainder[15 : 15+lengthBits])
subPackets = append(subPackets, subs...)
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
}
return subPackets, length
}
func parseLiteral(input string) (int, int) {
literal := ""
length := 0
for i := 0; i < len(input); i += 5 {
literal += string(input[i+1]) + string(input[i+2]) + string(input[i+3]) + string(input[i+4])
length += 5
if input[i] == '0' {
break
}
}
v, err := strconv.ParseInt(literal, 2, 64)
if err != nil {
fmt.Println("Unable to parse", literal, err)
return 0, -1
}
return int(v), length
}
func load(filename string) packet {
b := packet{}
file, err := os.Open(filename)
if err != nil {
return b
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
b = parseHex(scanner.Text())
}
return b
}

137
sixteen/bits_test.go Normal file
View File

@@ -0,0 +1,137 @@
package sixteen
import "testing"
func Test_hex(t *testing.T) {
original := "8A004A801A8002F478"
expected := 16
p := parseHex(original)
vSum := p.versionSum()
if vSum != expected {
t.Logf("Expected %d, found %d", expected, vSum)
t.Fail()
}
}
func Test_hex2(t *testing.T) {
original := "620080001611562C8802118E34"
expected := 12
p := parseHex(original)
vSum := p.versionSum()
if vSum != expected {
t.Logf("Expected %d, found %d", expected, vSum)
t.Fail()
}
}
func Test_hex3(t *testing.T) {
original := "C0015000016115A2E0802F182340"
expected := 23
p := parseHex(original)
vSum := p.versionSum()
if vSum != expected {
t.Logf("Expected %d, found %d", expected, vSum)
t.Fail()
}
}
func Test_hex4(t *testing.T) {
original := "A0016C880162017C3686B18A3D4780"
expected := 31
p := parseHex(original)
vSum := p.versionSum()
if vSum != expected {
t.Logf("Expected %d, found %d", expected, vSum)
// t.Fail()
}
}
func Test_type4(t *testing.T) {
b := parse("110100101111111000101000")
if b.version != 6 {
t.Logf("Expected version 6, found %d", b.version)
t.Fail()
}
if b.typeID != 4 {
t.Logf("Expected type 4, found %d", b.typeID)
t.Fail()
}
if b.content != 2021 {
t.Logf("Expected content to be 2021, found %d", b.content)
t.Fail()
}
}
func Test_operator(t *testing.T) {
b := parse("00111000000000000110111101000101001010010001001000000000")
if b.version != 1 {
t.Logf("Expected version 1, found %d", b.version)
t.Fail()
}
if b.typeID != 6 {
t.Logf("Expected type 6, found %d", b.typeID)
t.Fail()
}
if len(b.subpackets) != 2 {
t.Logf("Expected 2 subpacket, found %d", len(b.subpackets))
t.Fail()
}
if b.subpackets[0].content != 10 {
t.Logf("Expected first packet to be 10, found %d", b.subpackets[0].content)
t.Fail()
}
if b.subpackets[1].content != 20 {
t.Logf("Expected second packet to be 20, found %d", b.subpackets[2].content)
t.Fail()
}
}
func Test_operator2(t *testing.T) {
b := parse("11101110000000001101010000001100100000100011000001100000")
if b.version != 7 {
t.Logf("Expected version 1, found %d", b.version)
t.Fail()
}
if b.typeID != 3 {
t.Logf("Expected type 6, found %d", b.typeID)
t.Fail()
}
if len(b.subpackets) != 3 {
t.Logf("Expected 3 subpacket, found %d", len(b.subpackets))
t.FailNow()
}
if b.subpackets[0].content != 1 {
t.Logf("Expected first packet to be 1, found %d", b.subpackets[0].content)
t.Fail()
}
if b.subpackets[1].content != 2 {
t.Logf("Expected second packet to be 2, found %d", b.subpackets[2].content)
t.Fail()
}
if b.subpackets[2].content != 3 {
t.Logf("Expected third packet to be 3, found %d", b.subpackets[2].content)
t.Fail()
}
}

1
sixteen/input.txt Normal file
View File

@@ -0,0 +1 @@
220D6448300428021F9EFE668D3F5FD6025165C00C602FC980B45002A40400B402548808A310028400C001B5CC00B10029C0096011C0003C55003C0028270025400C1002E4F19099F7600142C801098CD0761290021B19627C1D3007E33C4A8A640143CE85CB9D49144C134927100823275CC28D9C01234BD21F8144A6F90D1B2804F39B972B13D9D60939384FE29BA3B8803535E8DF04F33BC4AFCAFC9E4EE32600C4E2F4896CE079802D4012148DF5ACB9C8DF5ACB9CD821007874014B4ECE1A8FEF9D1BCC72A293A0E801C7C9CA36A5A9D6396F8FCC52D18E91E77DD9EB16649AA9EC9DA4F4600ACE7F90DFA30BA160066A200FC448EB05C401B8291F22A2002051D247856600949C3C73A009C8F0CA7FBCCF77F88B0000B905A3C1802B3F7990E8029375AC7DDE2DCA20C2C1004E4BE9F392D0E90073D31634C0090667FF8D9E667FF8D9F0C01693F8FE8024000844688FF0900010D8EB0923A9802903F80357100663DC2987C0008744F8B5138803739EB67223C00E4CC74BA46B0AD42C001DE8392C0B0DE4E8F660095006AA200EC198671A00010E87F08E184FCD7840289C1995749197295AC265B2BFC76811381880193C8EE36C324F95CA69C26D92364B66779D63EA071008C360098002191A637C7310062224108C3263A600A49334C19100A1A000864728BF0980010E8571EE188803D19A294477008A595A53BC841526BE313D6F88CE7E16A7AC60401A9E80273728D2CC53728D2CCD2AA2600A466A007CE680E5E79EFEB07360041A6B20D0F4C021982C966D9810993B9E9F3B1C7970C00B9577300526F52FCAB3DF87EC01296AFBC1F3BC9A6200109309240156CC41B38015796EABCB7540804B7C00B926BD6AC36B1338C4717E7D7A76378C85D8043F947C966593FD2BBBCB27710E57FDF6A686E00EC229B4C9247300528029393EC3BAA32C9F61DD51925AD9AB2B001F72B2EE464C0139580D680232FA129668

25
sixteen/main.go Normal file
View File

@@ -0,0 +1,25 @@
package sixteen
import "fmt"
type Sixteen struct {
bits packet
}
func Init(filepath string) *Sixteen {
sixteen := &Sixteen{
bits: packet{},
}
sixteen.bits = load(filepath)
return sixteen
}
func (d *Sixteen) Answer() string {
return fmt.Sprintf("The sum of the version numbers is %d", d.bits.versionSum())
}
func (d *Sixteen) FollowUp() string {
return "sixteen part 2 answer for bits"
}