123 lines
2.1 KiB
Go
123 lines
2.1 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
_ "embed"
|
|
"fmt"
|
|
"slices"
|
|
"strings"
|
|
|
|
aoc "go.sour.is/advent-of-code-2023"
|
|
)
|
|
|
|
var log = aoc.Log
|
|
|
|
func main() { aoc.MustResult(aoc.Runner(run)) }
|
|
|
|
type result struct {
|
|
valuePT1 int
|
|
valuePT2 int
|
|
}
|
|
|
|
func (r result) String() string { return fmt.Sprintf("%#v", r) }
|
|
|
|
func run(scan *bufio.Scanner) (*result, error) {
|
|
r := &result{}
|
|
|
|
var ops []string
|
|
for scan.Scan() {
|
|
text := scan.Text()
|
|
ops = strings.Split(text, ",")
|
|
|
|
r.valuePT1 = aoc.Reduce(func(i int, t string, sum int) int {
|
|
sum += hash(t)
|
|
return sum
|
|
}, 0, ops...)
|
|
}
|
|
|
|
var boxen boxes
|
|
|
|
boxen = aoc.Reduce(func(i int, op string, b boxes) boxes {
|
|
return b.Op(op)
|
|
}, boxen, ops...)
|
|
|
|
r.valuePT2 = boxen.Sum()
|
|
|
|
log(boxen)
|
|
|
|
return r, nil
|
|
}
|
|
|
|
func hash(s string) int {
|
|
var sum int
|
|
for _, a := range s {
|
|
sum += int(a)
|
|
sum *= 17
|
|
sum %= 256
|
|
}
|
|
|
|
return sum
|
|
}
|
|
|
|
type lens struct {
|
|
label string
|
|
value int
|
|
}
|
|
type box []lens
|
|
type boxes [256]box
|
|
|
|
func (lis boxes) String() string {
|
|
var buf strings.Builder
|
|
buf.WriteString("Boxes:\n")
|
|
for i, b := range lis {
|
|
if len(b) > 0 {
|
|
fmt.Fprintf(&buf, "Box %d: %v\n",i, b)
|
|
}
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
func (lis box) String() string {
|
|
var buf strings.Builder
|
|
if len(lis) > 0 {
|
|
buf.WriteString(lis[0].String())
|
|
}
|
|
for _, l := range lis[1:] {
|
|
buf.WriteString(l.String())
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
func (l lens) String() string {
|
|
return fmt.Sprintf("[%s %d]", l.label, l.value)
|
|
}
|
|
|
|
func (lis boxes) Op(op string) boxes {
|
|
if a, _, ok := strings.Cut(op, "-"); ok {
|
|
i := hash(a)
|
|
pos := slices.IndexFunc(lis[i], func(l lens) bool { return l.label == a })
|
|
if pos >= 0 {
|
|
lis[i] = append(lis[i][:pos], lis[i][pos+1:]...)
|
|
}
|
|
} else if a, b, ok := strings.Cut(op, "="); ok {
|
|
i := hash(a)
|
|
pos := slices.IndexFunc(lis[i], func(l lens) bool { return l.label == a })
|
|
v := aoc.Atoi(b)
|
|
if pos == -1 {
|
|
lis[i] = append(lis[i], lens{a, v})
|
|
} else {
|
|
lis[i][pos].value = v
|
|
}
|
|
}
|
|
|
|
return lis
|
|
}
|
|
func (lis boxes) Sum() int {
|
|
sum := 0
|
|
for b := range lis {
|
|
for s := range lis[b] {
|
|
sum += (b+1) * (s+1) * lis[b][s].value
|
|
}
|
|
}
|
|
return sum
|
|
} |