Advent-of-Code-2023/day15/dayFifteen.go

149 lines
2.8 KiB
Go

package day15
import (
"fmt"
"log"
"os"
"regexp"
"slices"
"strconv"
"strings"
)
func Run() int {
fmt.Println("hello day 15")
log.Println("hello day 15")
filename := "day15/example"
bytes, err := os.ReadFile(filename)
if err != nil {
panic(fmt.Sprint("error reading file ", filename))
}
text := string(bytes)
text = strings.TrimSpace(text)
instructions := strings.Split(text, ",")
result := 0
boxes := make([]Box, 256)
for i, box := range boxes {
box.Focals = make(map[string]int)
boxes[i] = box
}
for _, instructionStr := range instructions {
i := ReadInstruction(instructionStr)
box := boxes[i.Box]
box.Act(i)
boxes[i.Box] = box
// result += ASCIIStringHash(instruction)
}
for i, box := range boxes {
if len(box.Labels) != 0 {
log.Printf("%d box %+v final state\n", i, box)
}
result += (i + 1) * box.FocusingPower()
}
return result
}
type Box struct {
Labels []string
Focals map[string]int
}
func (b *Box)Act(i Instruction) {
log.Printf("for box %+v instruction \n%s\n", b, i.String())
switch i.Action {
case Put:
_, found := b.Focals[i.Label]
if !found {
b.Labels = append(b.Labels, i.Label)
}
b.Focals[i.Label] = i.LensFocal
case Remove:
_, found := b.Focals[i.Label]
if !found {
return
}
index := slices.Index(b.Labels, i.Label)
delete(b.Focals, i.Label)
b.Labels = slices.Delete(b.Labels, index, index+1)
}
log.Printf("result : %+v\n", b)
return
}
func (b *Box)FocusingPower() int {
result := 0
for i, label := range b.Labels {
result += (i + 1) * b.Focals[label]
}
return result
}
type Action rune
const (
Put Action = '='
Remove = '-'
)
type Instruction struct {
Label string
Box int
Action Action
LensFocal int
}
func (i *Instruction) String() string {
operation := ""
switch i.Action {
case Put:
operation = "put into"
case Remove:
operation = "remove from"
}
return fmt.Sprintf("%s\t\t%d of focal %d %s", operation, i.Box, i.LensFocal, i.Label)
}
func ReadInstruction(str string) Instruction {
result := Instruction{}
re := regexp.MustCompile(`(?P<label>\D+)(?P<operation>[=\-])(?P<focal>\d*)`)
// log.Println("in str ", str)
fields := re.FindStringSubmatch(str)
// log.Printf("in %s found %+v", str, fields)
operation := fields[2]
operationRune := []rune(operation)[0]
result.Action = Action(operationRune)
if operationRune == '=' {
focalStr := fields[3]
focal, err := strconv.Atoi(focalStr)
if err != nil {
panic(fmt.Sprint("error reading focal from ", str))
}
result.LensFocal = focal
}
result.Label = fields[1]
result.Box = ASCIIStringHash(result.Label)
return result
}
func ASCIIStringHash(str string) int {
result := 0
for _, symb := range str {
result += int(symb)
result *= 17
result %= 256
}
return result
}