aoc24/day11/fixedNoTree.go

80 lines
2 KiB
Go
Raw Normal View History

2024-12-11 14:28:01 +00:00
package main
import (
"fmt"
"hash/fnv"
"strconv"
"sync"
"git.mstar.dev/mstar/goutils/other"
// "github.com/patrickmn/go-cache"
)
// var valCache = cache.New(time.Minute, time.Minute*2)
var valCacheMap = map[uint64]uint64{}
var mLock sync.RWMutex
func hash(val uint64, iter, maxIter int) uint64 {
h := fnv.New64a()
_, err := h.Write([]byte(fmt.Sprintf("%d.%d.%d", val, iter, maxIter)))
if err != nil {
panic(err)
}
return h.Sum64()
}
func fromCache(val uint64, iteration, maxIter int) (uint64, bool) {
mLock.RLock()
pv, ok := valCacheMap[hash(val, iteration, maxIter)]
mLock.RUnlock()
// v, ok := valCache.Get(strconv.FormatUint(hash(val, iteration, maxIter), 10))
// if !ok {
// return 0, false
// }
// pv, ok := v.(uint64)
return pv, ok
}
func intoCache(val uint64, iteration, maxIter int, result uint64) {
mLock.Lock()
valCacheMap[hash(val, iteration, maxIter)] = result
mLock.Unlock()
// valCache.Set(strconv.FormatUint(hash(val, iteration, maxIter), 10), result, -1)
}
func Advance(val uint64, iteration int, maxIter int) (out uint64) {
cacheVal, ok := fromCache(val, iteration, maxIter)
if ok {
return cacheVal
}
defer func() {
if _, ok := fromCache(val, iteration, maxIter); !ok {
intoCache(val, iteration, maxIter, out)
}
}()
// fmt.Printf("Iteration %d with val %d\n", iteration, val)
if iteration == maxIter {
// fmt.Println("1")
out = 1
return
}
if val == 0 {
// fmt.Println("0")
out = Advance(1, iteration+1, maxIter)
return
}
if len(strconv.FormatUint(val, 10))%2 == 0 {
// fmt.Println("Split")
str := strconv.FormatUint(val, 10)
// fmt.Println("format")
left := other.Must(strconv.ParseUint(string([]rune(str)[:len(str)/2]), 10, 64))
right := other.Must(strconv.ParseUint(string([]rune(str)[len(str)/2:]), 10, 64))
// fmt.Printf("l: %d, r: %d\n", left, right)
out = Advance(left, iteration+1, maxIter) + Advance(right, iteration+1, maxIter)
return
}
out = Advance(val*2024, iteration+1, maxIter)
return out
}