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 }