Completed both parts of Day 15 puzzle
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…
Reference in New Issue