def num_prime_subsets(S_lim, t): '''Return the number of of subsets of S (the set of all primes < S_lim), the sum of whose elements is a prime number. The result is returned modulo t.''' S = primes('lt', S_lim) # w[s] = how many subsets have sum s n = sum(S) + 1 w = [0L] * n # Set Initial condition. Include the empty set - convenient for DP. w[0] += 1L; w[S[0]] += 1L # DP over S elements for r in islice(S, 1, None): w = [(w[s] + (w[s - r] if s >= r else 0L)) % t for s in xrange(n)] return sum(w[s] for s in primes('lt', n)) % t
def E(n): # Slow! # r = np.array(list(enumerate([0] + [np.prod(factorize(x).keys()) for x in xrange(1, n + 1)])), dtype=np.uint) # return r[np.lexsort((r[:, 0], r[:, 1]))] r = np.ones((n + 1,), dtype=np.uint) for p in primes('lt', n + 1): r[p::p] *= p return sorted(enumerate(r), key=lambda (n, r): (r, n))
def sf(N): '''Returns the number of square-free numbers <= N.''' # Count the number of NON-square-free numbers x <= N of the form x = q^2 * y. q is composed of # primes <= sqrt(N), so we first enumerate all q = a single prime; thus we've counted q's of the # form p1*p2 twice, so we subtract combinations of two primes, add back combinations of three, etc. # (the inclusion-exclusion principle). N2 = N ** 0.5 P = map(long, primes('lt', int(ceil(N2)) + 1)) s, combos, count, index_of = 1, [((p,), p) for p in P], sum(N / (q * q) for q in P), dict((v, k) for k, v in enumerate(P)) while combos: # While there exist combinations (seq) of primes whose product (q) <= sqrt(N), append # all possible primes to each such combinations such that the product remains <= sqrt(N). c = [] for seq, q in combos: r_max = int(N2 / q) for j in xrange(index_of[seq[-1]] + 1, len(combos)): r = P[j] if r > r_max: break c.append((seq + (r,), q * r)) combos = c # Flip sign of these sequences' contributions - the inclusion- exclusion principle s = -s tot = s * sum(N / (q * q) for _, q in combos) count += tot # Return the complement of non-square-free numbers return N - count
def sum_s(N): p_list, s = map(int, primes("lt", int(1.05 * N))[2:]), 0 for i, p1 in enumerate(p_list[:-1]): if p1 > N: break s += s_pair(p1, p_list[i + 1]) return s
def circular_primes(n): """Returns the set of circule primes < n.""" p = filter(is_odd, primes("lt", n)) # Odd-digit prime list c = set([2]) for x in p: examine_prime(x, p, c) return c
def valid_combos(N, K, debug=False): '''Return all valid combinations of multiples of large primes (> N/K) in an inverse squares sum summing up to 0.5; a boolean array of appearance status (1=present, never present=0, -1=unknown), list of remaining primes <= N/K, and the list of unknown numbers in 2..N. K should be chosen to balance the runtimes of this method and the subsequent DFS''' p_list, left, bound, x, c, T = \ primes('lt', N + 1), 0, float(N) / K, -np.ones((N + 1), dtype=int), [], \ [None] + [list(combos(k)) for k in xrange(1, K + 1)] num_primes = len(p_list) known = set([]) while left < num_primes and p_list[left] < bound: left += 1 if debug: print 'N', N, 'K', K, 'All primes', p_list for p in p_list[left:]: k, p2 = N / p, p * p valid = [(np.array([(l + 1) * p for l in np.where(S)[0]]), np.array([(l + 1) * p for l in np.where(~S)[0]]), f / p2) for S, f in T[k] if f.numerator % p2 == 0] if valid: c.append(valid) if debug: print 'p', p, 'k', k, 'admissible combos', len(valid) for y in valid: print '\t', y known |= set([l * p for l in xrange(1, k + 1)]) else: x[p::p] = 0 c = [[(S, T, float(f)) for S, T, f in y] for y in c] unknown = np.array(sorted((set(np.where(x < 0)[0]) - known) - set([0, 1]))) known = sorted(known) if debug: print 'len(c)', len(c) print 'known (%d)' % (len(known,)), known print 'unknown (%d)' % (len(unknown,)), unknown return x, c, p_list[:left], unknown
def sum_using_other_factor(max_prime): s = 0 for p in islice(primes('lt', max_prime), 3, 100000000): a = A(p) other_fac = other_factor(a, ten_factors) if other_fac: s += p print p, a, other_fac, s return s + 10 # 10=2+3+5 = boundary case
def concate_set_brute_force(k, n_max, S_initial=list()): '''Min sum concat prime set of size k whose elements < n_max.''' S_min, s_min = None, 0 for S in it.ifilter(is_concat_set, (S_initial + list(x) for x in it.combinations(primes('lt', n_max), k - len(S_initial)))): # print '\t', S s = sum(S) if S_min is None or s < s_min: S_min, s_min = S, s return S_min
def sum_distinct_m(N): '''Return the sum of distinct M(p,q,N) for all p<q prime pairs.''' P, p_max = map(long, primes('lt', int(ceil(N * 0.5)) + 1)), N ** 0.5 return sum(max(p ** k * q ** l for k in xrange(1, int(log(float(N) / q) / log(p)) + 1) for l in xrange(1, int(log(float(N) / p ** k) / log(q)) + 1)) for (p, q) in ((p, q) for (i, p) in takewhile(lambda p: p[1] <= p_max, enumerate(P)) for q in (P[j] for j in takewhile(lambda j: P[j] <= N / P[i], xrange(i + 1, len(P))))))
def sum_primes_of_len(N, L): p = primes('lt', N) print 'N', N, '#primes', len(p) f = phi(N, p) print 'phi', f s = 0 for k, x in enumerate(long(x) for x in p): l = chain_len(f, x, L) if not (k % 10000): print x, l if l == L: s += x return s
def div_sums(N): '''Returns an array of all n''s <= N such that n/d + d is prime if d|n.''' s, P = np.zeros((N + 2,), dtype=bool), primes('lt', N + 2) s.fill(False); s[1] = True; s[P] = True; n = P - 1 print '|primes|', len(P) + 1 for d in xrange(2, int(N ** 0.5) + 1): # print 'd', d, 'n', n, n / d + d, s[n / d + d] d2 = d * d if n[-1] < d2: break n = n[(n % d != 0) | s[n / d + d]] if d % 1000 == 0: print 'd', d, '|n|', len(n) return n
def consecutive_n(N, offset, complement, mods_primes=50): '''Return n for which {n^2+x: x in offset} is prime and {n^2+x: x in complement} is not prime.''' # Tabulate permissible remainders n mod p for the first mods_primes primes p p_list = primes('first', mods_primes) nc = int(p_list[-1] ** 0.5) + 1 R = [[all((i2 + x) % p for x in offsets) for i2 in (i * i for i in xrange(p))] for p in p_list] # By the Chinese remainder theorem, n must be of the form 210q + [10|80|130|200] for s in [10, 80, 130, 200]: for n in xrange(s, N, 210): n2 = n * n # First check against remainder table; if passes, run the more expensive primality test if (n <= nc or all(R[i][n % p] for i, p in enumerate(p_list))) and \ all(isp(n2 + x) for x in offsets) and all(not isp(n2 + x) for x in complement): yield n
def min_n_above(S): s = 2 * S + 1 m = int(ceil(log(s) / log(3))) p = primes('first', m) fac, n, f = dict((x, factorize(x)) for x in xrange(1, p[-1])), prod([long(x) for x in p]), dict((x, 1) for x in p) while p.size: found, f0 = False, f.copy() del f0[p[-1]] for t in xrange(1, p[-1]): ft = f0.copy() for k, v in fac[t].iteritems(): ft[k] += v if prod([2 * k + 1 for k in ft.itervalues()]) > s: found, n, f, p = True, (n / p[-1]) * t, ft, p[:-1] break if not found: break return n
def num_solutions_dp(N): result = 0 K = N P = primes('lt', int(0.5 * (2 ** N * 5 ** K + 1)) + 1) print 'P', P N1 = -2 # int(np.floor(-1 - K * phi)) K1 = -2 # int(np.floor(-(N + 1) / phi)) print 'N1', N1, 'to N', N, 'x', 'K1', K1, 'to K', K # f_union = cummulative_union(N, K, P, F) f1 = F1(N, K, P) f2 = F2(N, K, P) f1_reduced = F1_reduced(F1(N, K, P)) f2_reduced = F2_reduced(F2(N, K, P)) f_union = f1_reduced + f2_reduced print 'F1\n', np.flipud(f1) print 'F2\n', np.flipud(f2) print 'F1_reduced\n', np.flipud(f1_reduced) print 'F2_reduced\n', np.flipud(f2_reduced) print 'F_reduced\n', np.flipud(f_union) g_union = cummulative_union(N1, K, P, G) # print 'g_union\n', np.flipud(g_union) h_union = cummulative_union(N, K1, P, H) # print 'h_union\n', np.flipud(h_union) t = np.zeros((N - N1 + 1, K - K1 + 1), dtype=int) t[-N1:, -K1:] = f_union t[1:-N1, -K1:] = np.flipud(g_union) t[-N1:, 1:-K1] = np.fliplr(h_union) print 't\n', np.flipud(t) s = np.zeros((N - N1 + 1, K - K1 + 1), dtype=long) for n in xrange(1, N - N1 + 1): for k in xrange(1, K - K1 + 1): if n >= 0 and k >= 0: s[n, k] = s[n - 1, k] + s[n, k - 1] - s[n - 1, k - 1] + t[n, k] elif n < 0 and k >= 0: s[n, k] = s[n, k - 1] + t[n, k] elif k < 0 and n >= 0: s[n, k] = s[n - 1, k] + t[n, k] else: s[n, k] = 0 if n >= -N1: result += s[n, n + N1 - K1] # print 'n', n, 'result', result print 's\n', np.flipud(s) return result
def sq_primes(N): """Return the list of primes of the form 2*n**2-1 for 1<n<=N.""" P = map(long, primes("lt", int(2 ** 0.5 * N) + 1)[1:]) # t(n) is always odd so omit divisibility-by-2 check s = np.zeros((N + 1,), dtype=bool) s[:] = True s[:2] = False for p in P: print "p", p h = (p + 1) / 2 if pow(h, (p - 1) / 2, p) == 1: a = sqrt_mod(h, p) # print '\t', 'h', h, 'a', a for q in (a, p - a): # print '\t', 'q', q, 'Sieving', range((p + q) if (2 * q * q - 1 == p) else q, len(s), p) s[(p + q) if (q * q == h) else q :: p] = False # print 's', s # print 'n', np.where(s)[0] return map(lambda n: 2 * n * n - 1, np.where(s)[0])
def _min_sum(k, num_primes): '''Return the min k-seq sum (k>=2). Search among the first num_primes (>=2) primes.''' p = primes('first', num_primes)[1:] # Exclude 2 since we know it cannot be in a valid sequence a, d, smin, N, min_d = [0], 1, 0, len(p), 0 # a contains indices into p min_pa = [] print 'N', N while True: pa = [p[x] for x in a] valid = valid_seq(pa) # print 'a', a, 'seq', pa, 'valid?', valid if valid: if d == k: # Found new candidate for min seq s = sum(pa) if smin == 0 or s < smin: smin, min_pa = s, pa print 'Valid sequence: ', s, pa a[-1] += 1 # Advance to next number at same depth else: a.append(a[-1] + 1) # Increase depth d += 1 else: a[-1] += 1 # print 'New a', a, 'smin', smin # Advance to next seq while d > min_d: # print '\t', a x = a[-1] if x == N or (smin > 0 and (sum(p[x] for x in a) >= smin if d == k else (x >= (smin - sum(p[x] for x in a) - 0.5 * (k - d - 1)) / (k - d)))): x = a.pop() d -= 1 if d > min_d: a[-1] += 1 else: break if d == min_d + 1: if a[0] % 10 == 0: print 'Starting at', p[a[0]] if d == min_d: # Exhausted search space break return smin, min_pa
def min_a_with_A_ge(N): '''Return the minimum n for which A(N)>=N.''' logN = log(N) / log(3) if logN < int(logN) + 1e-12: return N # N is a power of 3 p_low = 3 ** (int(logN)) p_high = 3 * p_low p = primes('lt', p_high) p = p[p > p_low] lim = lambda P: it.dropwhile(lambda (n, a): a != n - 1, ((n, A(n)) for n in P)).next()[0] # Find largest prime 3^[log3(N)] < p_min <= N such that A(n)=n-1 try: p_min = lim(reversed(p[p <= N])) except StopIteration: p_min = p_high # Find smallest prime N <= p_max < 3^([log3(N)]+1) such that A(n)=n-1 try: p_max = lim(p[p >= N]) except StopIteration: p_max = p_high # Search between p_min and p_max return it.dropwhile(lambda (_, a): a < N, ((n, A(n)) for n in xrange(p_min, p_max + 1) if gcd(n, 10) == 1)).next()[0]
def sum_s(n): p = primes('lt', 10 ** (0.5 * n)) return sum(it.dropwhile(lambda x: x[1] == 0, ((m, S(n, d, m, p)) for m in xrange(n - 1, 0, -1))).next()[1] for d in xrange(10))
============================================================ http://projecteuler.net/problem=146 The smallest positive integer n for which the numbers n2+1, n2+3, n2+7, n2+9, n2+13, and n2+27 are consecutive primes is 10. The sum of all such integers n below one-million is 1242490. What is the sum of all such integers n below 150 million? ============================================================ ''' from problem007 import primes from problem027 import is_prime from random import choice '''Fermat probable primality test''' N_LIST = 10 ** 6 SQRT_N_LIST = int(N_LIST ** 0.5) P = primes('lt', SQRT_N_LIST + 1) is_probable_prime = lambda n, tries = 20: all(pow(int(choice(P)), n - 1, n) == 1 for _ in xrange(tries)) isp = lambda x, tries = 20: is_prime(x, P) if x <= N_LIST else is_probable_prime(x, tries=tries) def consecutive_n(N, offset, complement, mods_primes=50): '''Return n for which {n^2+x: x in offset} is prime and {n^2+x: x in complement} is not prime.''' # Tabulate permissible remainders n mod p for the first mods_primes primes p p_list = primes('first', mods_primes) nc = int(p_list[-1] ** 0.5) + 1 R = [[all((i2 + x) % p for x in offsets) for i2 in (i * i for i in xrange(p))] for p in p_list] # By the Chinese remainder theorem, n must be of the form 210q + [10|80|130|200] for s in [10, 80, 130, 200]: for n in xrange(s, N, 210): n2 = n * n # First check against remainder table; if passes, run the more expensive primality test if (n <= nc or all(R[i][n % p] for i, p in enumerate(p_list))) and \
If N is admissible, the smallest integer M > 1 such that N+M is prime, will be called the pseudo-Fortunate number for N. For example, N=630 is admissible since it is even and its distinct prime factors are the consecutive primes 2,3,5 and 7. The next prime number after 631 is 641; hence, the pseudo-Fortunate number for 630 is M=11. It can also be seen that the pseudo-Fortunate number for 16 is 3. Find the sum of all distinct pseudo-Fortunate numbers for admissible numbers N less than 109. ============================================================ ''' from itertools import dropwhile, count from problem007 import primes from problem146 import is_probable_prime not_probable_prime = lambda x: not is_probable_prime(x) PRIMES = map(long, primes('lt', 100)) # First 100 primes enough for any limit < 1e36 def admissible_lt(limit, prime_index, n_prev): '''Generator of admissible numbers < N.''' # Enumerate admissible numbers by 2^k1 3^k2 ... pm^km by a DFS p = PRIMES[prime_index] n = n_prev * p while n < limit: yield n for k in admissible_lt(limit, prime_index + 1, n): yield k n *= p '''Distinct pseudo-fortunate numbers < N. Brute-force search over m for the smallest prime n+m for each admissible n.''' distinct_pf_lt = lambda limit: set(dropwhile(not_probable_prime, count(n + 2)).next() - n for n in admissible_lt(limit, 0, 1))
def sum_sf(N): b = list(islice(binom(), 0, N)) d = set([y for x in b for y in x]) p = map(lambda x: long(x * x), primes('lt', int(N + 1) + 1)) return sum(np.array(list(d))[np.array(map(lambda x: all(x % y for y in p), d))])
while N % p == 0: N /= p return N == 1 def prime_factors(B, primes=None): '''List of non-distinct primes factors of B(=F/4), B>=1.''' for p in (primes if primes is not None else Primes()): while B % p == 0: yield p B /= p if B == 1: break '''Sum of all n = p[0]^a0*...*p[k]^ak <= N with ai >= 0.''' g = lambda N, P: sum(n for n in xrange(1, N + 1) if p_prime(n, P)) '''Primes that are not 1(mod 4).''' p_primes = lambda L, include_two: ([2] if include_two else []) + filter(lambda x: x % 4 == 3, primes('lt', L + 1)) '''A generator of primes that are 1 (mod 4).''' primes1 = lambda: it.ifilter(lambda x: x % 4 == 1, it.imap(long, Primes())) '''Primes that are not 3(mod 4).''' not_p_primes = lambda L, include_two: ([2] if not include_two else []) + filter(lambda x: x % 4 == 1, it.imap(long, primes('lt', L + 1))) def sum_r(L, include_two): '''Sum of r = p[0]^a0*...*p[k]^ak <= L with p's = primes = 3(mod 4) <= N. Uses a sieve to calculate the complement of this sum.''' s = np.array([True] * (L + 1), dtype=bool); s[0] = False for p in not_p_primes(L, include_two): s[p::p] = False return sum(map(long, np.where(s)[0])) def q_combos(q_set, b, L):
def min_counterexample(limit): p = primes('lt', limit) is_composable = lambda x: any(it.imap(lambda y : is_int(math.sqrt((x - y) / 2)), it.takewhile(lambda y: y < x, p))) return it.dropwhile(is_composable, it.chain.from_iterable(xrange(p[k] + 2, p[k + 1], 2) for k in xrange(1, len(p) - 1))).next()
def max_sum_with_set_lookup(a): '''Return a max sum element in a sorted list a.''' a_set = set(a) n, L, max_s, limit = len(a), 0, a[0] - 1, a[-1] for i in xrange(n): s = sum(a[i:i + L]) if s > limit or i + L + 1 >= n: return max_s for j, q in enumerate(a[i + L:], L + 1): s += q if s > limit: break if s > max_s and s in a_set: L, max_s = j, s #print 'i', i, 'L', L, 'max_s', max_s, sum(a[i:i + L]), a[i:i + L] return None # Should only be reached if n=0 if __name__ == "__main__": # import doctest # doctest.testmod() import time start = time.time() print max_sum(primes('lt', 1000000)) print time.time() - start, 'sec' start = time.time() print max_sum_with_set_lookup(primes('lt', 1000000)) print time.time() - start, 'sec'
def sum_semi_divisible_bf(N): P = primes('lt', 2 * N ** 0.5) return sum(n for n in xrange(4, N + 1) if is_semi_divisible(n, P))
def __init__(self, n): self._n = n self._d = np.zeros((n,), dtype=np.uint) # d-values cache self._p = primes('lt', n) # Prime list self._d[self._p] = 1 # B.C. self._d[1] = 1
7 + 3 5 + 5 5 + 3 + 2 3 + 3 + 2 + 2 2 + 2 + 2 + 2 + 2 What is the first value which can be written as the sum of primes in over five thousand different ways? ============================================================ ''' import itertools as it from problem007 import primes def num_ways(n, terms): '''Return the number of ways to write each 0<=x<n as a sum of primes.''' w = [1] + [0] * (n - 1) for p in terms: for y in xrange(p, n): w[y] += w[y - p] print p, w return w def first_num(terms, criterion, W, n_min): n = n_min(W) while True: try: return it.dropwhile(lambda (_, w): criterion(w, W), enumerate(num_ways(n, terms(n)))).next()[0] except StopIteration: n *= 2 if __name__ == "__main__": print first_num(lambda n: primes('lt', n), lambda w, W: w <= W, 5000, lambda W: max(W / 10, 5))
''' ============================================================ http://projecteuler.net/problem=118 Using all of the digits 1 through 9 and concatenating them freely to form decimal integers, different sets can be formed. Interestingly with the set {2,5,47,89,631}, all of the elements belonging to it are prime. How many distinct sets containing each of the digits one through nine exactly once contain only prime elements? ============================================================ ''' import itertools as it from math import log10, ceil from problem007 import primes from problem027 import is_prime P = primes('lt', int(98765432 ** 0.5) + 1) is_p = lambda x: is_prime(x, P) '''Digits = set of remaining digits. n_min = maximum number in set so far.''' # num_prime_sets = lambda digits, n_min: sum(num_prime_sets(digits - set(map(int, str(x))), x) for x in # it.ifilter(is_p, xrange(n_min + 1, min(100000000, int(''.join(sorted(map(str, digits), reverse=True))) + 1)))) if digits else 1 def num_prime_sets(digits, n_min, n_max=None): if not digits: return 1 digits_str = map(str, digits) eligible = (lambda x: x > n_min and x <= n_max and is_p(x)) if n_max else (lambda x: x > n_min and is_p(x)) max_digits = min(8, len(digits)) if n_max: max_digits = min(max_digits, int(ceil(log10(n_max)))) x_primes = it.ifilter(eligible, (int(''.join(x)) for r in xrange(1, max_digits + 1) for x in it.permutations(digits_str, r))) return sum(num_prime_sets(digits - set(map(int, str(x))), x) for x in x_primes) if __name__ == "__main__": print num_prime_sets(set(range(1, 10)), 0, 9876)
def num_comp2(N): p_limit = int(ceil(N - 1) ** 0.5) P = primes('lt', int(ceil(N - 1) * 0.5) + 1) # Sorted ascending return sum(sum(1 for _ in takewhile(lambda q: q <= q_limit, P[k:])) for (k, q_limit) in ((k, N / p) for k, p in enumerate(takewhile(lambda p: p <= p_limit, P))))
''' ============================================================ http://projecteuler.net/problem=243 http://projecteuler.net/problem=243 ============================================================ ''' from problem007 import primes from numpy import prod if __name__ == "__main__": # Calculated that 2*3*...*23 is not large enough and 29*this number is. So trying # multiples of this number until becomes large enough. print 4 * prod(primes('lt', 29))