Completed both parts of Day 15 puzzle

main
oabrivard 2 years ago
parent c7025518ab
commit 08d1136101

@ -0,0 +1,171 @@
package day15
import "strconv"
func hash(bytes []byte) int {
val := 0
for _, b := range bytes {
val += int(b)
val *= 17
val %= 256
}
return val
}
func SumHashes(line string) int {
result := 0
l := []byte(line)
step := []byte{}
for _, b := range l {
if b == '\n' {
break
}
if b == ',' {
hashValue := hash(step)
result += hashValue
step = []byte{}
} else {
step = append(step, b)
}
}
return result
}
type Lense struct {
label string
focal int
}
type Lenses []*Lense
type LensePresences map[string]int
type Box struct {
lenses Lenses
lensePresences LensePresences
}
func parseStep(bytes []byte) (string, byte, int) {
label := []byte{}
focal := []byte{}
parseFocal := false
for _, b := range bytes {
if b == '-' {
return string(label), '-', -1
}
if b == '=' {
parseFocal = true
continue
}
if parseFocal {
focal = append(focal, b)
} else {
label = append(label, b)
}
}
focalValue, _ := strconv.Atoi(string(focal))
return string(label), '=', focalValue
}
func removeLense(box *Box, label string) {
idx, ok := box.lensePresences[label]
if ok {
delete(box.lensePresences, label)
/*
idx := 0
for i, lense := range box.lenses {
if lense.label == label {
idx = i
break
}
}
*/
for i := idx; i < len(box.lenses)-1; i++ {
box.lenses[i] = box.lenses[i+1]
box.lensePresences[box.lenses[i].label] = i
}
box.lenses = box.lenses[0 : len(box.lenses)-1]
}
}
func addOrChangeLense(box *Box, label string, focal int) {
newLense := &Lense{label, focal}
idx, ok := box.lensePresences[label]
if ok { // change lense
box.lenses[idx] = newLense
} else {
// add lense
box.lenses = append(box.lenses, newLense)
box.lensePresences[label] = len(box.lenses) - 1
}
}
func SumBoxes(line string) int {
l := []byte(line)
boxes := make([]*Box, 256)
step := []byte{}
for _, b := range l {
if b == '\n' {
break
}
if b == ',' {
label, operator, focal := parseStep(step)
labelHash := hash([]byte(label))
box := boxes[labelHash]
if box == nil {
box = &Box{Lenses{}, LensePresences{}}
boxes[labelHash] = box
}
if operator == '-' {
removeLense(box, label)
if len(box.lenses) == 0 {
box = nil
boxes[labelHash] = nil
}
} else {
addOrChangeLense(box, label, focal)
}
step = []byte{}
} else {
step = append(step, b)
}
}
sum := 0
for i, box := range boxes {
if box != nil {
boxNumber := i + 1
for j, lense := range box.lenses {
slotNumber := j + 1
focusingPower := boxNumber * slotNumber * lense.focal
sum += focusingPower
}
}
}
return sum
}

@ -0,0 +1,75 @@
package day15
import (
"testing"
"gitea.paas.celticinfo.fr/oabrivard/aoc2023/utils"
)
func TestHash(t *testing.T) {
result := hash([]byte("rn=1"))
if result != 30 {
t.Fatalf("expected 30, got %v", result)
}
result = hash([]byte("cm-"))
if result != 253 {
t.Fatalf("expected 253, got %v", result)
}
result = hash([]byte("qp=3"))
if result != 97 {
t.Fatalf("expected 97, got %v", result)
}
result = hash([]byte("cm=2"))
if result != 47 {
t.Fatalf("expected 47, got %v", result)
}
result = hash([]byte("qp-"))
if result != 14 {
t.Fatalf("expected 14, got %v", result)
}
}
func TestSumHashes(t *testing.T) {
result := SumHashes("rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7,")
if result != 1320 {
t.Fatalf("expected 1320, got %v", result)
}
}
func TestSumHashesWithInput(t *testing.T) {
lines := utils.ReadLines("input.txt")
result := SumHashes(lines[0])
if result != 511416 {
t.Fatalf("expected 511416, got %v", result)
}
}
func TestSumBoxes(t *testing.T) {
result := SumBoxes("rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7,")
if result != 145 {
t.Fatalf("expected 145, got %v", result)
}
}
func TestSumBoxesWithInput(t *testing.T) {
lines := utils.ReadLines("input.txt")
result := SumBoxes(lines[0])
if result != 290779 {
t.Fatalf("expected 290779, got %v", result)
}
}

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save