79 lines
2 KiB
Go
79 lines
2 KiB
Go
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
|
|
}
|