예제 #1
0
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
예제 #2
0
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))
예제 #3
0
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
예제 #4
0
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
예제 #5
0
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
예제 #6
0
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
예제 #7
0
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
예제 #8
0
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
예제 #9
0
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))))))
예제 #10
0
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
예제 #11
0
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
예제 #12
0
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
예제 #13
0
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
예제 #14
0
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
예제 #15
0
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])
예제 #16
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
예제 #17
0
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]
예제 #18
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))
예제 #19
0
============================================================
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 \
예제 #20
0
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))
예제 #21
0
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))])
예제 #22
0
        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):
예제 #23
0
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()
예제 #24
0
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'
예제 #25
0
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))
예제 #26
0
 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
예제 #27
0
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))
예제 #28
0
'''
============================================================
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)
예제 #29
0
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)))) 
예제 #30
0
'''
============================================================
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))