import sys
import math
if sys.version_info < (3,):
range = xrange
def primes(upto, func):
if upto > 25000: return large_primes(upto, func)
upto -= 1
flags = [True] * upto
for i in range(upto-1):
if flags[i]:
prime = i + 2
k = i + prime
while k < upto:
flags[k] = False
k += prime
func(prime)
def large_primes(upto, func):
# The Algorithm is adapted from http://w...content-available-to-author-only...k.com/~jrm/printprimes.html
# This code is a translated version of Andreas Raab's #largePrimesUpTo:do: method
# which was written for the Squeak Smalltalk environment.
idx_limit = math.sqrt(upto) + 1
flags = [0xFF] * (int((upto + 2309) / 2310) * 60 + 60)
primes_up_to_2310 = []
primes(2310, lambda p: primes_up_to_2310.append(p))
mask_bit_idx = [None]*2310
mask_bit_idx[0] = 0
mask_bit_idx[1] = 1
bit_idx = 1
for i in range(5):
func(primes_up_to_2310[i])
idx = 5
for n in range(2, 2310):
while primes_up_to_2310[idx] < n: idx += 1
if n == primes_up_to_2310[idx]:
bit_idx += 1
mask_bit_idx[n] = bit_idx
elif n % 2 == 0 or n % 3 == 0 or n % 5 == 0 or n % 7 == 0 or n % 11 == 0:
mask_bit_idx[n] = 0
else:
bit_idx += 1
mask_bit_idx[n] = bit_idx
for n in range(13, upto, 2):
mask_bit = mask_bit_idx[n % 2310]
if mask_bit:
byte_idx = int(n / 2310) * 60 + (mask_bit-1 >> 3)
bit_idx = 1 << (mask_bit & 7)
if flags[byte_idx] & bit_idx:
func(n)
if n < idx_limit:
idx = n * n
if (idx & 1) == 0: idx += n
while idx <= upto:
mask_bit = mask_bit_idx[idx % 2310]
if mask_bit:
byte_idx = int(idx / 2310) * 60 + (mask_bit-1 >> 3)
mask_bit = 255 - (1 << (mask_bit & 7))
flags[byte_idx] = flags[byte_idx] & mask_bit
idx += 2 * n
max = int(sys.argv[1]) if len(sys.argv) == 2 else 100
q = c = 0
def f(p):
global q, c
q = p
c += 1
primes(max, f)
print(q, c)
aW1wb3J0IHN5cwppbXBvcnQgbWF0aAoKaWYgc3lzLnZlcnNpb25faW5mbyA8ICgzLCk6CiAgICByYW5nZSA9IHhyYW5nZQoKZGVmIHByaW1lcyh1cHRvLCBmdW5jKToKICAgIGlmIHVwdG8gPiAyNTAwMDogcmV0dXJuIGxhcmdlX3ByaW1lcyh1cHRvLCBmdW5jKQogICAgdXB0byAtPSAxCiAgICBmbGFncyA9IFtUcnVlXSAqIHVwdG8KICAgIGZvciBpIGluIHJhbmdlKHVwdG8tMSk6CiAgICAgICAgaWYgZmxhZ3NbaV06CiAgICAgICAgICAgIHByaW1lID0gaSArIDIKICAgICAgICAgICAgayA9IGkgKyBwcmltZQogICAgICAgICAgICB3aGlsZSBrIDwgdXB0bzoKICAgICAgICAgICAgICAgIGZsYWdzW2tdID0gRmFsc2UKICAgICAgICAgICAgICAgIGsgKz0gcHJpbWUKICAgICAgICAgICAgZnVuYyhwcmltZSkKCmRlZiBsYXJnZV9wcmltZXModXB0bywgZnVuYyk6CiAgICAjIFRoZSBBbGdvcml0aG0gaXMgYWRhcHRlZCBmcm9tIGh0dHA6Ly93Li4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5rLmNvbS9+anJtL3ByaW50cHJpbWVzLmh0bWwKICAgICMgVGhpcyBjb2RlIGlzIGEgdHJhbnNsYXRlZCB2ZXJzaW9uIG9mIEFuZHJlYXMgUmFhYidzICNsYXJnZVByaW1lc1VwVG86ZG86IG1ldGhvZAogICAgIyB3aGljaCB3YXMgd3JpdHRlbiBmb3IgdGhlIFNxdWVhayBTbWFsbHRhbGsgZW52aXJvbm1lbnQuCgogICAgaWR4X2xpbWl0ID0gbWF0aC5zcXJ0KHVwdG8pICsgMQogICAgZmxhZ3MgPSBbMHhGRl0gKiAoaW50KCh1cHRvICsgMjMwOSkgLyAyMzEwKSAqIDYwICsgNjApCiAgICBwcmltZXNfdXBfdG9fMjMxMCA9IFtdCiAgICBwcmltZXMoMjMxMCwgbGFtYmRhIHA6IHByaW1lc191cF90b18yMzEwLmFwcGVuZChwKSkKICAgIG1hc2tfYml0X2lkeCA9IFtOb25lXSoyMzEwCiAgICBtYXNrX2JpdF9pZHhbMF0gPSAwCiAgICBtYXNrX2JpdF9pZHhbMV0gPSAxCiAgICBiaXRfaWR4ID0gMQogICAgZm9yIGkgaW4gcmFuZ2UoNSk6CiAgICAgICAgZnVuYyhwcmltZXNfdXBfdG9fMjMxMFtpXSkKICAgIGlkeCA9IDUKICAgIGZvciBuIGluIHJhbmdlKDIsIDIzMTApOgogICAgICAgIHdoaWxlIHByaW1lc191cF90b18yMzEwW2lkeF0gPCBuOiBpZHggKz0gMQogICAgICAgIGlmIG4gPT0gcHJpbWVzX3VwX3RvXzIzMTBbaWR4XToKICAgICAgICAgICAgYml0X2lkeCArPSAxCiAgICAgICAgICAgIG1hc2tfYml0X2lkeFtuXSA9IGJpdF9pZHgKICAgICAgICBlbGlmIG4gJSAyID09IDAgb3IgbiAlIDMgPT0gMCBvciBuICUgNSA9PSAwIG9yIG4gJSA3ID09IDAgb3IgbiAlIDExID09IDA6CiAgICAgICAgICAgIG1hc2tfYml0X2lkeFtuXSA9IDAKICAgICAgICBlbHNlOgogICAgICAgICAgICBiaXRfaWR4ICs9IDEKICAgICAgICAgICAgbWFza19iaXRfaWR4W25dID0gYml0X2lkeAogICAgZm9yIG4gaW4gcmFuZ2UoMTMsIHVwdG8sIDIpOgogICAgICAgIG1hc2tfYml0ID0gbWFza19iaXRfaWR4W24gJSAyMzEwXQogICAgICAgIGlmIG1hc2tfYml0OgogICAgICAgICAgICBieXRlX2lkeCA9IGludChuIC8gMjMxMCkgKiA2MCArIChtYXNrX2JpdC0xID4+IDMpCiAgICAgICAgICAgIGJpdF9pZHggPSAxIDw8IChtYXNrX2JpdCAmIDcpCiAgICAgICAgICAgIGlmIGZsYWdzW2J5dGVfaWR4XSAmIGJpdF9pZHg6CiAgICAgICAgICAgICAgICBmdW5jKG4pCiAgICAgICAgICAgICAgICBpZiBuIDwgaWR4X2xpbWl0OgogICAgICAgICAgICAgICAgICAgIGlkeCA9IG4gKiBuCiAgICAgICAgICAgICAgICAgICAgaWYgKGlkeCAmIDEpID09IDA6IGlkeCArPSBuCiAgICAgICAgICAgICAgICAgICAgd2hpbGUgaWR4IDw9IHVwdG86CiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tfYml0ID0gbWFza19iaXRfaWR4W2lkeCAlIDIzMTBdCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIG1hc2tfYml0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZV9pZHggPSBpbnQoaWR4IC8gMjMxMCkgKiA2MCArIChtYXNrX2JpdC0xID4+IDMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrX2JpdCA9IDI1NSAtICgxIDw8IChtYXNrX2JpdCAmIDcpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3NbYnl0ZV9pZHhdID0gZmxhZ3NbYnl0ZV9pZHhdICYgbWFza19iaXQKICAgICAgICAgICAgICAgICAgICAgICAgaWR4ICs9IDIgKiBuCgptYXggPSBpbnQoc3lzLmFyZ3ZbMV0pIGlmIGxlbihzeXMuYXJndikgPT0gMiBlbHNlIDEwMApxID0gYyA9IDAKCmRlZiBmKHApOgogICAgZ2xvYmFsIHEsIGMKICAgIHEgPSBwCiAgICBjICs9IDEKCnByaW1lcyhtYXgsIGYpCnByaW50KHEsIGMpCg==