[ prog / sol / mona ]

prog


LISP Puzzles

67 2020-05-03 00:01

[1/2]
The improved version of >>36 uses stacked self-generation of the S sequence and third-order S-groups to achieve O(log(log(n))) space consumption and O(n^(1/8)) runtime. As explained in >>35 a third-order S-group is a group of second-order S-groups, and this is folded into the R value in one step. The constant factor that results from the more complex S-group folding step is considerably higher than in >>36.

def seq4_covered (s, c, S1):
   # start, count
   incR, incS = seq3_inc (s, c, S1 - 1)
   return incR

def seq4_inc (s, c, S0, S1, covered):
   # start, count
   incS1   = seq3_sum1sc (s, c)
   countS1 = incS1 - c

   incS0   = countS1 * S1 + seq3_inc (s, c, 0) [0]
   countS0 = covered
   overR   = (incS0 - 1) * incS0 // 2
   backR   = (
      countS1 * (countS1 + 1) // 2 * S1
      - countS1 + seq4_backR (s, c)
   )
   incR    = overR - backR + S0 * countS0
   return (incR, incS0, incS1)

def seq4_backR (s, c):
   # start, count
   return c*(((((5*c + (30*s - 29))*c + ((60*s - 130)*s + 45))*c + (((40*s - 140)*s + 90)*s + 85))*c + ((-60*s + 250)*s - 290))*c + (20*s - 160)*s + 184) // 240

def work_seq4 (n):
   seq3covered = seq3_covered
   seq3inc     = seq3_inc
   seq4next    = seq2_next
   seq3sum1sc  = seq3_sum1sc
   seq4covered = seq4_covered
   seq4inc     = seq4_inc

   levels       = []
   R, S0, S1    = 3, 4, 4
   start, count = 4, 3
   advance      = seq4covered (start, count, S1)
   covered      = 2 + advance

   while covered <= n:
      incR, incS0, incS1 = seq4inc (start, count, S0, S1, advance)
      R  += incR
      S0 += incS0
      S1 += incS1
      start, count = seq4next (levels, 0)
      advance      = seq4covered (start, count, S1)
      covered     += advance

   print ("levels:", len (levels))

   covered     -= advance
   fakelevels   = [[start, count, 0, S1]]
   start, count = seq4next (fakelevels, 0)
   advance      = seq3covered (start, count)
   covered     += advance

   while covered <= n:
      incR, incS0 = seq3inc (start, count, S0)
      R  += incR
      S0 += incS0
      start, count = seq4next (fakelevels, 0)
      advance      = seq3covered (start, count)
      covered     += advance

   covered     -= advance
   fakelevels   = [[start, count, 0, S0]]
   start, count = seq4next (fakelevels, 0)
   covered     += count

   while covered < n:
      R += seq3sum1sc (start, count)
      start, count = seq4next (fakelevels, 0)
      covered     += count

   R += seq3sum1sc (start, count - (covered - n))
   return R

The timing for R(10^20) is down to about 80 milliseconds in vanilla python from the previous 300 milliseconds:

$ python3 -m timeit -s 'import flake.hofs as mod' 'mod.work_seq4 (100000000000000000000)'
10 loops, best of 3: 81.2 msec per loop

The timing for R(10^30) is about 14 seconds in vanilla python:

$ python3 -m timeit -s 'import flake.hofs as mod' 'mod.work_seq4 (1000000000000000000000000000000)'
10 loops, best of 3: 14.3 sec per loop

The first integer k for which R(10^k) overflows an u256 is k=39. The value of R(10^39) is
500000000000000000029814239694953305682145634502486118475654808671411192582303

$ g4 39
k 39 index 1000000000000000000000000000000000000000
levels: 5
1000000000000000000000000000000000000000 -> 500000000000000000029814239694953305682145634502486118475654808671411192582303 0x4516DF8A16FE63D603196794A678455A328B511811E5818CC6F66DDCD067DD09F 259
157


VIP:

do not edit these