def generate_lists(primemax): global plist1, plist2 plist = lib.list_primes2(primemax) plist1, plist2 = [3], [3] for i in range(3, len(plist)): if plist[i] % 3 == 1: plist1.append(plist[i]) else: plist2.append(plist[i]) print(': generated lists, max =', primemax, ', mod3=1 size =', len(plist1), ', mod3=2 size =', len(plist2))
def initialize_caches(primemax): print(': initializing caches with prime limit =', primemax) global primecache1, primecache2, paircache1, paircache2 primelist = lib.list_primes2(primemax) # starts with 2,3,5,7 primecache1, primecache2 = [3], [3] # separately insert 3 for i in range(3, len(primelist)): # split cache if primelist[i] % 3 == 1: primecache1.append(primelist[i]) else: primecache2.append(primelist[i]) # will have mod3 value = 2 print(': generate split prime lists, len(mod3=1) =', len(primecache1), ', len(mod3=2) =', len(primecache2)) paircache1 = list( list(False for c in range(len(primecache1))) for r in range(len(primecache1))) paircache2 = list( list(False for c in range(len(primecache2))) for r in range(len(primecache2))) for i, pi in enumerate( primecache1): # generate mod3=1 pair primality cache ibase = pi # use to shift left based on digits in prime index j nextleftshift = 1 for j, pj in enumerate(primecache1): if i == j: continue # would have factor 11 or 101 or 1001, ... if pj >= nextleftshift: ibase *= 10 nextleftshift *= 10 conc = ibase + pj paircache1[i][j] = is_prime(conc) print(': generated lookup table for mod3=1') for i, pi in enumerate( primecache2): # generate mod3=2 pair primality cache ibase = pi nextleftshift = 1 for j, pj in enumerate(primecache2): if i == j: continue if pj >= nextleftshift: ibase *= 10 nextleftshift *= 10 conc = ibase + pj paircache2[i][j] = is_prime(conc) print(': generated lookup table for mod3=2') print(': done')
import libtkoz as lib sumways = 5000 # dynamic programming maxprime = 32 while True: # increase prime limit until finding a solution ways = [0] * (maxprime + 1) plist = lib.list_primes2(maxprime) ways[0] = 1 # 1 way, nothing, for when first prime selected is itself ways[1] = 0 # not prime, no smaller primes for p in plist: # add how many ways i=p+k --> k as sum of primes <= p for i in range(p, maxprime + 1): ways[i] += ways[i - p] solution = -1 for i, w in enumerate(ways): # find satisfying number if w > sumways: solution = i break if solution != -1: # found a satisfying number print(':', solution, 'can be expressed in', ways[solution], 'ways') print(solution) break maxprime *= 2
import libtkoz as lib import math import functools # ~3min with cpython / core2 q8200 # appears to scale linear to sqrt(N) N = 10**16 modulus = 10**9 + 7 primes = lib.list_primes2(int(math.sqrt(N))) print(': sieved primes') # determine max value of k prod = 1 ktable = [0] for p in primes: prod *= p * p if prod > N: break ktable.append(0) # for each k, count how many numbers are divisible by all prime squares in # every combination of k prime squares # product of squares, number of factors, next prime index def recurse(sqprod, numpfactors, nextpi): global N, primes, ktable maxsq = N // sqprod while nextpi < len(primes) and primes[nextpi]**2 <= maxsq: recurse(sqprod * primes[nextpi]**2, numpfactors + 1, nextpi + 1) nextpi += 1
def C(n): assert n > 0 pin = len(lib.list_primes2(n)) return 6 * (5**(n - pin - 1)) * sum( 5**(pin - i) * lib.binom_coeff(n - 1, i) for i in range(pin + 1))
import libtkoz as lib factorsexp = 500500 modulus = 500500507 # large enough so pi(sievelim) >= factorsexp # may need up to this many primes # if not large enough, program will crash with list index out of bounds sievelim = 8000000 # use a sieve (index i represents 2i+1) (prime=True) # every time reaching a prime, mark its square # requires only 1 sweep over the sieve, ~4sec (i5-2540m) sieve = lib.list_primes2(sievelim, return_sieve=True) evenval = 2 sievei = 1 # 2*1+1=3 initially result = 1 counted = 0 while counted < factorsexp: # iterate over sieve if evenval < 2 * sievei + 1: # more optimal to pick exponent of 2 result = (result * evenval) % modulus evenval *= evenval counted += 1 else: if sieve[sievei]: # prime, multiply this one n = 2 * sievei + 1 result = (result * n) % modulus n *= n # mark square in sieve n //= 2 # sieve index of square if n < len(sieve): sieve[n] = True # mark so it is multiplied
import libtkoz as lib smax = 24 modulus = 10**9 # ~4sec (pypy / i5-2540m) and ~50sec (cpython / i5-2540m) fib = [0, 1] # generate fibonacci numbers while len(fib) <= smax: fib.append(fib[-2] + fib[-1]) numsums = [0] * (fib[-1] + 1) # i: sum of numbers whose prime factors sum to i numsums[0] = 1 # needed for dynamic programming primes = lib.list_primes2(fib[-1]) for p in primes: # if p is added to factorizations of i, those numbers get multiplied by p # numsums[i] is sum for numbers using prime factors at most p # suppose numsums has sums for numbers using factors below p # if p is considered at index i, then we take numbers whose factors sum to # i-p and add a p to them, this is equivalent to multiplying those numbers # by p so we add that quantity to the index for i for i in range(p, len(numsums)): numsums[i] = (numsums[i] + p * numsums[i - p]) % modulus # sum fibonacci indexes print(sum(numsums[fib[f]] for f in range(2, smax + 1)) % modulus)
import libtkoz as lib import math divisors = 8 maximum = 10**6 #10**12 primes = lib.list_primes2(maximum) #1+math.floor(math.sqrt(maximum))) # find factorizations of how many divisors # the prime factorization of numbers with that many divisors must have exponents # 1 less than each factor dfactorizations = [] def d_factor(factors, n, prevf): global dfactorizations, divisors if n == divisors: dfactorizations.append(factors) else: # factor remaining part recursively rem = divisors // n while prevf * prevf <= rem: if rem % prevf == 0: d_factor(factors + [prevf], n * prevf, prevf) prevf += 1 d_factor(factors + [rem], divisors, rem) d_factor([], 1, 2) print(':', dfactorizations) count = 0
# find the solution pn = 2 # approximate p_n with binary method while 2*int(pn/math.log(pn))*pn < modexceed: pn *= 2 pn //= 2 # step back add = pn // 2 while add != 0: pn += add if 2*int(pn/math.log(pn))*pn > modexceed: pn -= add add //= 2 print(': estimated p_n =',pn,'with n ~=',int(pn/math.log(pn))) # step back to find prime near p_n while not lib.miller_rabin_verified(pn): pn -= 1 print(': found prime value p_n =',pn) # count primes n = len(lib.list_primes2(pn)) print(': found n =',n) # count down if needed while 2*n*pn > modexceed: n -= 1 pn -= 1 # find previous prime while not lib.miller_rabin_verified(pn): pn -= 1 # go up to first n value that exceeds while 2*n*pn <= modexceed: n += 1 pn += 1 while not lib.miller_rabin_verified(pn): pn += 1 print(': found p_',n,' = ',pn,' with product 2*n*p_n = ',2*n*pn,sep='') # the only thing left now is to make sure the prime index n is odd so we get # 2*n*p_n instead of 2 as the remainder if n % 2 == 0: n += 1
import libtkoz as lib import math # brute force with prime cache cache = lib.list_primes2(10000,return_set=True) cachemax = max(cache) def is_prime(n): if n <= cachemax: return n in cache return lib.prime(n) n = 9 while True: # loop to test composites if not is_prime(n): satisfiesconjecture = False for s in range(1, int(math.sqrt(n//2))+1): # find a square that works if is_prime(n - 2*s*s): satisfiesconjecture = True break if not satisfiesconjecture: print(n) break n += 2
import libtkoz as lib pval = 10**8 modulus = 10**9 + 7 # improved to sublinear pi sequence checking (after generating prime list) # primes uses O(n) memory, primeset uses O(n/logn) and so does picache # pi sequences require about logn/loglogn steps # main loop looks at all primes (O(n/logn)) so overall is about O(n/loglogn) # make prime list for iteration and prime set for fast primality checking primes = lib.list_primes2(pval) print(': listed primes up to', pval) # values of pi(n) for O(1) computation, go up to maximum pi(n) value picache = [] primeset = set() # make for fast primality checking of smaller numbers for i, p in enumerate(primes): # pi(p)=i+1 primeset.add(p) while len(picache) < p: picache.append(i) picache.append(i + 1) if p > len(primes): break print(': generated pi(n) cache up to', len(picache) - 1) longest = 2 # find longest possible pi sequence length n = len(primes) # (pval,pi(pval)) while n != 1: n = picache[n] longest += 1 print(': longest pi sequence length is', longest)
import libtkoz as lib arange = 999 # -999 to 999 brange = 1000 # -1000 to 1000 pseqlenparam = 100 # estimate for longer sequences to determine prime cache size # quadratic function is x^2+ax+b # computing next: f(x+1) - f(x) = (x^2+2x+1+ax+a+b) - (x^2+ax+b) # = 2x+1+a --> use this as difference to compute next more efficiently # generate a set of primes to quickly look up # if x may go up to 100, 100^2+1000*100+1000 ~= 10^5 --> seems reasonable # pick the largest term at x=100 ptablemax = max(pseqlenparam**2, pseqlenparam*arange, brange) ptable = lib.list_primes2(ptablemax,return_set=True) def prime(n): global ptable global ptablemax return (n <= ptablemax and n in ptable) or lib.prime(n) print(': listed', len(ptable), 'primes <=', ptablemax) # f(x) = x^2 + ax + b # f(0) = b --> b must be prime # f(1) = 1 + a + b --> if b odd then a must be odd # f(x+1) - f(x) = 2x + 1 + a --> a must be odd so the step size is even if arange % 2 == 0: arange -= 1 # ensure it is odd mostprimes = 0 amost, bmost = 0, 0 for b in range(3, brange+1, 2): if not prime(b): continue for a in range(-arange, arange+1, 2):
import libtkoz as lib truncprimesexist = 11 primecachesize = 100000 # maximum number to cache # cut down from 1 million made it a lot faster primecache = lib.list_primes2(primecachesize, return_set=True) # test primality with cache def is_prime(p): global primecachesize global primecache if p < primecachesize: return p in primecache else: return lib.prime(p) # functions to test prime truncatable properties, assumes number itself is prime def right_trunc(p): # just divide by 10 (integer division) p //= 10 while p != 0: if not is_prime(p): return False p //= 10 return True def left_trunc(p): # use strings for simplicity while p >= 10: # at least 2 digits, can truncate another p = int(str(p)[1:]) if not is_prime(p): return False return True
import libtkoz as lib import math maximum = 10**8 # ~1min and 2GiB RAM (pypy / i5-2540m) # start with a prime set for fast prime checking and a list of booleans for each # number that starts as true, once a composite d+n/d is found mark it false # only need to test d up to sqrt(n) because if d>sqrt(d) then n/d<sqrt(d) but # n/d is also a divisor so we would have already tested n/d+n/(n/d)=d+n/d # list primes up to 1 more since if d=n then n+n/n=n+1 # make a set of primes for fast prime testing (set containment) primes = lib.list_primes2(maximum + 1, return_set=True) print(': listed primes up to', maximum + 1) # set to false once a composite d+n/d is found nums = [True] * (maximum + 1) for d in range(1, 1 + int(math.sqrt(maximum))): nd = d # n/d value, d/d=1, 2d/d=2, ..., incremented in loop for n in range(d * d, maximum + 1, d): # every number d divides if not ((d + nd) in primes): nums[n] = False nd += 1 # sum indexes in nums list print(sum(n for n in range(maximum + 1) if nums[n]))
import libtkoz as lib import math limit = 1000000 primes = lib.list_primes2(limit, return_set=True) # brute force try everything, ~0.5 sec (i5-2540m) circulars = {2, 5} for n in range(3, limit, 2): if not n in primes or n in circulars: continue nn = n max10pow = int(math.log10(n)) # largest exp of 10 in number circular = True for i in range(max10pow): # do all rotations nn = (nn // 10) + (nn % 10) * (10**max10pow) if not nn in primes: circular = False break if circular: # insert all rotations print(': inserting rotations of', n) circulars.add(n) nn = n for i in range(max10pow): nn = (nn // 10) + (nn % 10) * (10**max10pow) circulars.add(nn) print(':', nn) print(':', sorted(list(circulars))) print(len(circulars))
import libtkoz as lib seqlen = 3 # currently hardcoded, has no effect digits = 4 # brute force primes = lib.list_primes2(10**digits) print(': listed', len(primes), 'primes') def is_prime(n): # assumes it would be in the primes list, binary search global primes l, h = 0, len(primes) while l != h: mid = (l + h) // 2 if primes[mid] >= n: h = mid else: l = mid + 1 return l < len(primes) and primes[l] == n # binary search for lowest 4 digit prime l, h = 0, len(primes) while l != h: m = (l + h) // 2 if primes[m] >= (10**(digits - 1)): h = m else: l = m + 1 print(': start prime index', l, 'is', primes[l]) done = False for i in range(l, len(primes)): # select first prime pi = primes[i]
import libtkoz as lib familysize = 8 # assert familysize in [8, 9, 10] primelim = 100000 primecache = lib.list_primes2(primelim, return_set=True) def is_prime(n): global primelim, primecache if n > primelim: return lib.prime(n) return n in primecache # suppose we replace some number of digits, use digit sum for 3 divisibility # if d digits are replaced, digit sum starts at s if the digits are 0 then # the digit sums will be s,s+d,s+2d,...,s+9d # at least 8 must not be divisible by 3 # if d is not divisible by 3 then 3 or 4 of the sums are divisible by 3 # at most 7 could be prime in that case so for 8,9,10 digit replacements, # we must replace 3,6,9,... digits def advance_permutation(l): # lexicographic order, increasing order i1 = len(l) - 1 while i1 > 0 and l[i1 - 1] >= l[i1]: i1 -= 1 # break decrease order i1 -= 1 if i1 == -1: return None # already maximum i2 = len(l) - 1
import libtkoz as lib limit = 1000000 primes = lib.list_primes2(limit) primeset = set(primes) # for fast lookup longestseq = 1 bestprime = 0 for i in range(len(primes)): if i > limit / longestseq: break # cant make longer sequence total = sum(primes[i:i + longestseq]) seqlen = longestseq for j in range(i + longestseq, len(primes)): total += primes[j] if total >= limit: break # done for this starting number seqlen += 1 if total in primeset: print(':', total, 'is sum of', seqlen, 'primes, start =', primes[i]) longestseq, bestprime = seqlen, total print(bestprime)
import libtkoz as lib primelim = 5000 modulus = 10**16 # generate primes and build sets 1 element at a time # maintain a list than keeps track of how many subsets sum to each number # keep a running cumulative sum of primes so the list can be dynamically # expanded as the highest possible sum increases with each new prime # lastly list primes up to the sum of primes in the set and use those as the # indexes for computing the sum (count subsets with prime sums) # takes ~2min (cpython / i5-2540m) pset = lib.list_primes2(primelim - 1) # number of subsets with each sum setswithsum = [1] # start with empty set # build the set 1 element at a time n = 0 psumcumulative = 0 # keep track of this to dynamically grow the list for p in pset: n += 1 psumcumulative += p # sets with sum i = original amount + p added to sets with sum i-p newlist = setswithsum[:] + ([0] * p) for i in range(p, psumcumulative + 1): newlist[i] = (newlist[i] + setswithsum[i - p]) % modulus setswithsum = newlist # assert sum(setswithsum)%modulus == (2**n)%modulus
import libtkoz as lib setsize = 5 # number of primes in prime pair set assert setsize >= 2 # prime cache to speed up primality checking pclim = 1000000 pcset = lib.list_primes2(pclim, return_set=True) def is_prime(n): if n <= pclim: return n in pcset return lib.prime(n) print(': generated primality checking cache with limit =', pclim) # brute force with some optimizations, took ~23min (i5-2540m) (very long !!!) # first observation: 2 or 5 cant be in the set # every prime in the set must have same mod3 value (all 1 or all 2) # if 1 and 2 are mixed, concatenating those 2 gives a number divisible by 3 # based on this, split the prime caches based on their mod3 value # additionally, 3 may be used in these so each cache half must have 3 # the caches take a very long time to generate relative to how long the # recursion spends searching candidate prime sets # just by observation, recursing was almost instant, even for large limits primecache1, primecache2 = [], [] # split based on mod3 value paircache1, paircache2 = [[]], [[]]
import libtkoz as lib import math nlim = 150 * 10**6 steps = [1, 3, 7, 9, 13, 27] # use an observation for efficiency, faster with miller rabin test # prime list eliminates lots of candidates, then the amount of use of the # miller rabin test is small so it can complete quickly after that # ~7sec (pypy / i5-2540m) # if some n=qx+r, a prime q, integer x, and remainder r, # n^2+s = q^2*x^2 + 2qxr + r^2+s # so if q | r^2+s then q | n^2+s plistsize = int(math.sqrt(nlim)) plist = lib.list_primes2(plistsize) candidates = [] for n in range(10, nlim, 10): # for each n, if a prime q divides r^2+s then it cant be a solution number fail = False # n cant be a candidate if this becomes true for q in plist: # use primes to eliminate many possibilities # skip primes above n since for primality, we only need to test # up to n for n^2+s if fail or q > n: break r = n % q r *= r # represents r^2 for s in steps: if (r + s) % q == 0: fail = True break
import libtkoz as lib import math limit = 10**8 # sieve, then pick a prime p and count how many primes q >= p such that # pq <= limit, so its summing pi(limit/p)-pi(p-1) for every p<=sqrt(limit) # sieving primes takes long but summing is fast since computing pi(n) can be # done efficiently with a prime list and binary search # ~18sec (cpython / i5-2540m) # start by listing primes up to half the limit since 2*p plist = lib.list_primes2(limit // 2) limitsqrt = int(math.sqrt(limit)) print(': listed primes up to', limit // 2) # for every prime p up to sqrt(limit), count how many primes there are from p # to limit/p, this can be done efficiently with binary search # the desired value is pi(limit/p) - pi(p-1), pi(n) is count of primes <= n # count primes up to n, correct results if n < next prime after plist[-1] def pi(n): global plist # find index of first prime to exceed n, pi(n) is num primes below this l, h = 0, len(plist) # partition while l != h: m = (l + h) // 2 # middle point, splits are [l,m] and [m+1,h) if plist[m] > n: h = m else: l = m + 1 return l
import libtkoz as lib import math limit = 50000000 # brute force by looping over a prime list, ~1sec (i5-2540m) # begin by listing primes up to sqrt(limit) primes = lib.list_primes2(int(math.sqrt(limit))) print(': generated primes up to', int(math.sqrt(limit))) sieve = set() # numbers that are expressible as the sum # this doubled speed, rather than allocate a length 50 million array for p2 in range(len(primes)): sum2 = primes[p2]**2 # sum the square, wont exceed limit for p3 in range(len(primes)): sum23 = sum2 + primes[p3]**3 if sum23 >= limit: break for p4 in range(len(primes)): sum234 = sum23 + primes[p4]**4 if sum234 >= limit: break sieve.add(sum234) print(len(sieve))