1
0
Fork 0

Compare commits

...

2 Commits

5 changed files with 347 additions and 0 deletions

View File

@ -0,0 +1,34 @@
package day15
import (
"bytes"
"fmt"
"log"
"os"
"path/filepath"
"testing"
"source.toby3d.me/toby3d/adventofcode/internal/day15/part1"
"source.toby3d.me/toby3d/adventofcode/internal/day15/part2"
)
var input []byte
func TestMain(m *testing.M) {
var err error
if input, err = os.ReadFile(filepath.Join("testdata", "input")); err != nil {
log.Fatalln("cannot open input file:", err)
}
os.Exit(m.Run())
}
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,56 @@
package part1
import (
"bufio"
"io"
)
type (
Sequence []Step
Step []byte
)
func (s Step) Sum() uint {
var result uint
for i := range s {
result += uint(s[i])
result *= 17
result = result % 256
}
return result
}
func (s Sequence) Sum() uint {
var result uint
for i := range s {
result += s[i].Sum()
}
return 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
}

View File

@ -0,0 +1,44 @@
package part1_test
import (
"fmt"
"strings"
"testing"
"source.toby3d.me/toby3d/adventofcode/internal/day15/part1"
)
func TestStep_Sum(t *testing.T) {
t.Parallel()
const expect uint = 52
step := part1.Step("HASH")
if actual := step.Sum(); actual != expect {
t.Errorf("want %d, got %d", expect, 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 := part1.ParseSequence(strings.NewReader(input))
for i := range seq {
fmt.Println(string(seq[i]), "becomes", seq[i].Sum())
}
fmt.Println(seq.Sum())
// Output:
// rn=1 becomes 30
// cm- becomes 253
// qp=3 becomes 97
// cm=2 becomes 47
// qp- becomes 14
// pc=4 becomes 180
// ot=9 becomes 9
// ab=5 becomes 197
// pc- becomes 48
// pc=6 becomes 214
// ot=7 becomes 231
// 1320
}

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
}