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 }