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 415
The total risk of the least risky path is 2864 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/one"
"unsupervised.ca/aoc2021/seven" "unsupervised.ca/aoc2021/seven"
"unsupervised.ca/aoc2021/six" "unsupervised.ca/aoc2021/six"
"unsupervised.ca/aoc2021/sixteen"
"unsupervised.ca/aoc2021/ten" "unsupervised.ca/aoc2021/ten"
"unsupervised.ca/aoc2021/thirteen" "unsupervised.ca/aoc2021/thirteen"
"unsupervised.ca/aoc2021/three" "unsupervised.ca/aoc2021/three"
@@ -67,6 +68,8 @@ func main() {
day = fourteen.Init("fourteen/input.txt") day = fourteen.Init("fourteen/input.txt")
case "fifteen": case "fifteen":
day = fifteen.Init("fifteen/input.txt") day = fifteen.Init("fifteen/input.txt")
case "sixteen":
day = sixteen.Init("sixteen/input.txt")
default: default:
fmt.Printf("%q does not have a solution.\n", flagParts[1]) fmt.Printf("%q does not have a solution.\n", flagParts[1])
help() 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"
}