1
0
Fork 0

Created part two solution for day 15 puzzle

This commit is contained in:
Maxim Lebedev 2023-12-15 22:34:10 +06:00
parent ef35183f2e
commit e292edaf62
Signed by: toby3d
GPG Key ID: 1F14E25B7C119FC5
3 changed files with 219 additions and 0 deletions

View File

@ -9,6 +9,7 @@ import (
"testing"
"source.toby3d.me/toby3d/adventofcode/internal/day15/part1"
"source.toby3d.me/toby3d/adventofcode/internal/day15/part2"
)
var input []byte
@ -26,3 +27,8 @@ func Example() {
fmt.Println(part1.ParseSequence(bytes.NewReader(input)).Sum())
// Output: 514639
}
func Example_PartTwo() {
fmt.Println(part2.ParseSequence(bytes.NewReader(input)).Sum())
// Output: 279470
}

View File

@ -0,0 +1,118 @@
package part2
import (
"bufio"
"bytes"
"io"
"slices"
)
type (
Sequence []Step
Step []byte
Lens struct {
label []byte
length int
}
)
func (s Step) Sum() uint {
var result uint
for i := range s.Hash() {
result += uint(s[i])
result *= 17
result = result % 256
}
return result
}
func (s Step) IsRemove() bool {
return bytes.IndexByte(s, '-') != -1
}
func (s Step) IsMove() bool {
return bytes.IndexByte(s, '=') != -1
}
func (s Step) Hash() []byte {
return s[:max(bytes.IndexByte(s, '-'), bytes.IndexByte(s, '='))]
}
func (s Step) Length() int {
index := max(bytes.IndexByte(s, '-'), bytes.IndexByte(s, '='))
if index == len(s)-1 {
return 0
}
return int(s[index+1] - '0')
}
func (s Sequence) Sum() uint64 {
var boxes [256][]Lens
for i := range s {
box := &boxes[int(s[i].Sum())]
index := slices.IndexFunc(*box, func(l Lens) bool {
return bytes.Equal(l.label, s[i].Hash())
})
switch {
default:
continue
case s[i].IsRemove() && index != -1:
*box = slices.Delete(*box, index, index+1)
case s[i].IsMove():
if index != -1 {
(*box)[index] = Lens{
label: s[i].Hash(),
length: s[i].Length(),
}
} else {
*box = append(*box, Lens{
label: s[i].Hash(),
length: s[i].Length(),
})
}
}
}
var result int
for i := range boxes {
for j := range boxes[i] {
result += (i + 1) * (j + 1) * boxes[i][j].length
}
}
return uint64(result)
}
func ParseSequence(r io.Reader) Sequence {
scanner := bufio.NewScanner(r)
scanner.Split(bufio.ScanBytes)
seq := make(Sequence, 0)
step := make(Step, 0)
for scanner.Scan() {
b := scanner.Bytes()[0]
switch b {
case ',', '\n':
seq = append(seq, step)
step = make(Step, 0)
continue
}
step = append(step, b)
}
return seq
}
func (s Step) GoString() string {
return string(s)
}

View File

@ -0,0 +1,95 @@
package part2_test
import (
"fmt"
"strings"
"testing"
"source.toby3d.me/toby3d/adventofcode/internal/day15/part2"
)
func TestStep_Hash(t *testing.T) {
t.Parallel()
for name, tc := range map[string]struct {
expect string
input part2.Step
}{
"rn=1": {input: part2.Step("rn=1"), expect: "rn"},
"cm-": {input: part2.Step("cm-"), expect: "cm"},
"qp=3": {input: part2.Step("qp=3"), expect: "qp"},
"cm=2": {input: part2.Step("cm=2"), expect: "cm"},
"qp-": {input: part2.Step("qp-"), expect: "qp"},
"pc=4": {input: part2.Step("pc=4"), expect: "pc"},
"ot=9": {input: part2.Step("ot=9"), expect: "ot"},
"ab=5": {input: part2.Step("ab=5"), expect: "ab"},
"pc-": {input: part2.Step("pc-"), expect: "pc"},
"pc=6": {input: part2.Step("pc=6"), expect: "pc"},
"ot=7": {input: part2.Step("ot=7"), expect: "ot"},
} {
name, tc := name, tc
t.Run(name, func(t *testing.T) {
t.Parallel()
if actual := string(tc.input.Hash()); actual != tc.expect {
t.Errorf("want '%s', got '%s'", tc.expect, actual)
}
})
}
}
func TestStep_Length(t *testing.T) {
t.Parallel()
for name, tc := range map[string]struct {
input part2.Step
expect int
}{
"rn=1": {input: part2.Step("rn=1"), expect: 1},
"cm-": {input: part2.Step("cm-"), expect: 0},
"qp=3": {input: part2.Step("qp=3"), expect: 3},
"cm=2": {input: part2.Step("cm=2"), expect: 2},
"qp-": {input: part2.Step("qp-"), expect: 0},
"pc=4": {input: part2.Step("pc=4"), expect: 4},
"ot=9": {input: part2.Step("ot=9"), expect: 9},
"ab=5": {input: part2.Step("ab=5"), expect: 5},
"pc-": {input: part2.Step("pc-"), expect: 0},
"pc=6": {input: part2.Step("pc=6"), expect: 6},
"ot=7": {input: part2.Step("ot=7"), expect: 7},
} {
name, tc := name, tc
t.Run(name, func(t *testing.T) {
t.Parallel()
if actual := tc.input.Length(); actual != tc.expect {
t.Errorf("want %d, got %d", tc.expect, actual)
}
})
}
}
func TestStep_IsRemove(t *testing.T) {
t.Parallel()
if actual := part2.Step("qp-").IsRemove(); !actual {
t.Errorf("want %t, got %t", true, actual)
}
}
func TestStep_IsMove(t *testing.T) {
t.Parallel()
if actual := part2.Step("rn=1").IsMove(); !actual {
t.Errorf("want %t, got %t", true, actual)
}
}
func Example() {
input := "rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7\n"
seq := part2.ParseSequence(strings.NewReader(input))
fmt.Println(seq.Sum())
// Output: 145
}