দ্রুততম হোম প্রাইম জেনারেটর


23

হোম প্রাইম কি?

উদাহরণস্বরূপ, এইচপি নিন (4)। প্রথমত, প্রধান কারণগুলি সন্ধান করুন। 4 এর প্রধান কারণগুলি ( সর্বনিম্ন থেকে সর্বকালের সর্ব্বতমিক সংখ্যাতে) 2, 2 are কারণগুলিকে আক্ষরিক সংখ্যা হিসাবে ধরুন। ২, ২ টি 22 হয়ে যায় fact

number    prime factors
4         2, 2
22        2, 11
211       211 is prime

আপনি একবার একটি মৌলিক সংখ্যায় পৌঁছে, ক্রম শেষ হয়। এইচপি (4) = 211। 14 এর সাথে এখানে একটি দীর্ঘ উদাহরণ দেওয়া হল:

number    prime factors
14        2, 7
27        3, 3, 3
333       3, 3, 37
3337      47, 71
4771      13, 367
13367     13367 is prime

আপনার চ্যালেঞ্জটি এমন একটি প্রোগ্রাম তৈরি করা যা এইচপি (এক্স) প্রদত্ত এক্স গণনা করবে এবং যত তাড়াতাড়ি সম্ভব এটি করবে । আপনি পরিচিত হোম প্রাইমগুলির তালিকা ব্যতীত আপনার যা কিছু সংস্থান চান তা ব্যবহার করতে পারেন।

লক্ষ্য করুন, এই সংখ্যাগুলি খুব দ্রুত খুব দ্রুত হয়ে যায়। এক্স = 8 এ, এইচপি (এক্স) সমস্তভাবে 3331113965338635107 এ লাফিয়ে যায়। এইচপি (49) এখনও খুঁজে পাওয়া যায় নি।

নীচের ইনপুটগুলির গড় গড়ে একটি রাস্পবেরি পাই 2 এ প্রোগ্রামের গতি পরীক্ষা করা হবে:

16
20
64
65
80

আপনার যদি একটি রাস্পবেরি পাই 2 থাকে তবে প্রোগ্রামটি নিজেই করুন, তারপরে সময় গড় করুন।


3
যত তাড়াতাড়ি সম্ভব সংজ্ঞায়িত করুন ।
LegionMammal978

1
@ লেজিওনম্যামাল978 সেরা রানটাইম পারফরম্যান্স সহ। এটি একটি দ্রুততম কোড চ্যালেঞ্জ।
নোহ এল


1
আমরা কীভাবে জানি যে কোন কোডটি দ্রুত? কিছু মানুষ একটি পাঁচ বছর বয়সী ল্যাপটপ (চালু পরীক্ষা করা যেতে পারে কাশি আমার মত কাশি ,) অন্যরা কিছু হাই-এন্ড ডেস্কটপ / সার্ভার ব্যবহার করতে পারেন। এছাড়াও, একই ভাষার অনুবাদকদের মধ্যে পারফরম্যান্স পরিবর্তিত হয়।
জংহওয়ান মিন

1
মিলার-রবিনের মতো কোনও সম্ভাব্য প্রাথমিক পরীক্ষা ব্যবহারের অনুমতি কি?
মাইল মাইল

উত্তর:


6

গণিত, এইচপি (80) ~ 0.88 এর মধ্যে

NestWhile[
  FromDigits[
    Flatten[IntegerDigits /@ 
      ConstantArray @@@ FactorInteger[#]]] &, #, CompositeQ] &

বেনামে ফাংশন। ইনপুট হিসাবে একটি সংখ্যা নেয় এবং আউটপুট হিসাবে একটি নম্বর প্রদান করে।


1শেষে সেখানে থাকার কথা নয় ...
JungHwan ন্যূনতম

আমার কম্পিউটারে ম্যাথেমেটিকা ​​নেই, অর্থাত আমার রাস্পবেরি পাই ২ এ এটি পরীক্ষা করাতে হবে (এবং বাকি প্রোগ্রামগুলি)
নোহ এল

যেহেতু আমরা golfing করছি না: আছে CompositeQজন্য !PrimeQ(এটিও নিশ্চিত করে যে আপনার উত্তর ইনপুটের চিরকালের লুপ না 1)।
মার্টিন এন্ডার

কীভাবে সম্ভব যে HP(80)গাণিতিকিকা কোথাও প্রাইমকে হার্ডকড না করে এত অল্প সময়ে পারফর্ম করে ? আমার আই laptop ল্যাপটপটি প্রাথমিকতা পরীক্ষা করতে কয়েক ঘন্টা সময় নিচ্ছে, পাশাপাশি HP(80)এটি কখন আসবে তার মূল কারণগুলি সন্ধান করতে পারে 47109211289720051
মারিও

@ নোএলএল ম্যাথমেটিকাকে অনলাইনে পরীক্ষা করা যায়। meta.codegolf.stackexchange.com/a/1445/34718
mbomb007

5

পাইপাই 5.4.1 64 বিট (লিনাক্স), এইচপি (80) ~ 1.54 এস

32 বিট সংস্করণটি কিছুটা ধীর হয়ে যাবে।

আমি অভিজ্ঞতার সাথে নির্ধারিত ব্রেকপয়েন্ট সহ চারটি পৃথক নির্ণয়ের পদ্ধতি ব্যবহার করি:

আমি ইসিএফ এবং এমপিকিউএসের মধ্যে একটি পরিষ্কার বিরতি খুঁজতে কিছুক্ষণ চেষ্টা করেছি, তবে এটির একটি বলে মনে হচ্ছে না। যাইহোক, যদি এন একটি ছোট ফ্যাক্টর থাকে, ইসিএফ সাধারণত এটি প্রায় তাত্ক্ষণিকভাবে খুঁজে পেতে পারে, সুতরাং আমি এমপিকিউএসে যাওয়ার আগে কেবল কয়েকটি বক্ররেখা পরীক্ষা করতে পছন্দ করেছি।

বর্তমানে এটি ম্যাথমেটিকার তুলনায় মাত্র 2x ডলার, যা আমি অবশ্যই একটি সাফল্য হিসাবে বিবেচনা করি।


home-prime.py

import math
import my_math
import mpqs

max_trial = 1e10
max_pollard = 1e22

def factor(n):
  if n < max_trial:
    return factor_trial(n)
  for p in my_math.small_primes:
    if n%p == 0:
      return [p] + factor(n/p)
  if my_math.is_prime(n):
    return [n]
  if n < max_pollard:
    p = pollard_rho(n)
  else:
    p = lenstra_ecf(n) or mpqs.mpqs(n)
  return factor(p) + factor(n/p)


def factor_trial(n):
  a = []
  for p in my_math.small_primes:
    while n%p == 0:
      a += [p]
      n /= p
  i = 211
  while i*i < n:
    for o in my_math.offsets:
      i += o
      while n%i == 0:
        a += [i]
        n /= i
  if n > 1:
    a += [n]
  return a


def pollard_rho(n):
  # Brent's variant
  y, r, q = 0, 1, 1
  c, m = 9, 40
  g = 1
  while g == 1:
    x = y
    for i in range(r):
      y = (y*y + c) % n
    k = 0
    while k < r and g == 1:
      ys = y
      for j in range(min(m, r-k)):
        y = (y*y + c) % n
        q = q*abs(x-y) % n
      g = my_math.gcd(q, n)
      k += m
    r *= 2
  if g == n:
    ys = (ys*ys + c) % n
    g = gcd(n, abs(x-ys))
    while g == 1:
      ys = (ys*ys + c) % n
      g = gcd(n, abs(x-ys))
  return g

def ec_add((x1, z1), (x2, z2), (x0, z0), n):
  t1, t2 = (x1-z1)*(x2+z2), (x1+z1)*(x2-z2)
  x, z = t1+t2, t1-t2
  return (z0*x*x % n, x0*z*z % n)

def ec_double((x, z), (a, b), n):
  t1 = x+z; t1 *= t1
  t2 = x-z; t2 *= t2
  t3 = t1 - t2
  t4 = 4*b*t2
  return (t1*t4 % n, t3*(t4 + a*t3) % n)

def ec_multiply(k, p, C, n):
  # Montgomery ladder algorithm
  p0 = p
  q, p = p, ec_double(p, C, n)
  b = k >> 1
  while b > (b & -b):
    b ^= b & -b
  while b:
    if k&b:
      q, p = ec_add(p, q, p0, n), ec_double(p, C, n)
    else:
      q, p = ec_double(q, C, n), ec_add(p, q, p0, n),
    b >>= 1
  return q

def lenstra_ecf(n, m = 5):
  # Montgomery curves w/ Suyama parameterization.
  # Based on pseudocode found in:
  # "Implementing the Elliptic Curve Method of Factoring in Reconfigurable Hardware"
  # Gaj, Kris et. al
  # http://www.hyperelliptic.org/tanja/SHARCS/talks06/Gaj.pdf
  # Phase 2 is not implemented.
  B1, B2 = 8, 13
  for i in range(m):
    pg = my_math.primes()
    p = pg.next()
    k = 1
    while p < B1:
      k *= p**int(math.log(B1, p))
      p = pg.next()
    for s in range(B1, B2):
      u, v = s*s-5, 4*s
      x = u*u*u
      z = v*v*v
      t = pow(v-u, 3, n)
      P = (x, z)
      C = (t*(3*u+v) % n, 4*x*v % n)
      Q = ec_multiply(k, P, C, n)
      g = my_math.gcd(Q[1], n)
      if 1 < g < n: return g
    B1, B2 = B2, B1 + B2


if __name__ == '__main__':
  import time
  import sys
  for n in sys.argv[1:]:
    t0 = time.time()
    i = int(n)
    f = []
    while len(f) != 1:
      f = sorted(factor(i))
      #print i, f
      i = int(''.join(map(str, f)))
    t1 = time.time()-t0
    print n, i
    print '%.3fs'%(t1)
    print

নমুনা সময়

    $ pypy home-prime.py 8 16 20 64 65 80
8 3331113965338635107
0.005s

16 31636373
0.001s

20 3318308475676071413
0.004s

64 1272505013723
0.000s

65 1381321118321175157763339900357651
0.397s

80 313169138727147145210044974146858220729781791489
1.537s

5 টির গড় প্রায় 0.39s।


নির্ভরতা

mpqs.pyআমার উত্তর থেকে খুব সামান্য কিছু সংশোধনীর সাথে দ্রুততম সেমিপ্রাইম ফ্যাক্টেরাইজেশনে নেওয়া হয়।

mpqs.py

import math
import my_math
import time

# Multiple Polynomial Quadratic Sieve
def mpqs(n, verbose=False):
  if verbose:
    time1 = time.time()

  root_n = my_math.isqrt(n)
  root_2n = my_math.isqrt(n+n)

  # formula chosen by experimentation
  # seems to be close to optimal for n < 10^50
  bound = int(5 * math.log(n, 10)**2)

  prime = []
  mod_root = []
  log_p = []
  num_prime = 0

  # find a number of small primes for which n is a quadratic residue
  p = 2
  while p < bound or num_prime < 3:

    # legendre (n|p) is only defined for odd p
    if p > 2:
      leg = my_math.legendre(n, p)
    else:
      leg = n & 1

    if leg == 1:
      prime += [p]
      mod_root += [int(my_math.mod_sqrt(n, p))]
      log_p += [math.log(p, 10)]
      num_prime += 1
    elif leg == 0:
      if verbose:
        print 'trial division found factors:'
        print p, 'x', n/p
      return p

    p = my_math.next_prime(p)

  # size of the sieve
  x_max = bound*8

  # maximum value on the sieved range
  m_val = (x_max * root_2n) >> 1

  # fudging the threshold down a bit makes it easier to find powers of primes as factors
  # as well as partial-partial relationships, but it also makes the smoothness check slower.
  # there's a happy medium somewhere, depending on how efficient the smoothness check is
  thresh = math.log(m_val, 10) * 0.735

  # skip small primes. they contribute very little to the log sum
  # and add a lot of unnecessary entries to the table
  # instead, fudge the threshold down a bit, assuming ~1/4 of them pass
  min_prime = int(thresh*3)
  fudge = sum(log_p[i] for i,p in enumerate(prime) if p < min_prime)/4
  thresh -= fudge

  sieve_primes = [p for p in prime if p >= min_prime]
  sp_idx = prime.index(sieve_primes[0])

  if verbose:
    print 'smoothness bound:', bound
    print 'sieve size:', x_max
    print 'log threshold:', thresh
    print 'skipping primes less than:', min_prime

  smooth = []
  used_prime = set()
  partial = {}
  num_smooth = 0
  prev_num_smooth = 0
  num_used_prime = 0
  num_partial = 0
  num_poly = 0
  root_A = my_math.isqrt(root_2n / x_max)

  if verbose:
    print 'sieving for smooths...'
  while True:
    # find an integer value A such that:
    # A is =~ sqrt(2*n) / x_max
    # A is a perfect square
    # sqrt(A) is prime, and n is a quadratic residue mod sqrt(A)
    while True:
      root_A = my_math.next_prime(root_A)
      leg = my_math.legendre(n, root_A)
      if leg == 1:
        break
      elif leg == 0:
        if verbose:
          print 'dumb luck found factors:'
          print root_A, 'x', n/root_A
        return root_A

    A = root_A * root_A

    # solve for an adequate B
    # B*B is a quadratic residue mod n, such that B*B-A*C = n
    # this is unsolvable if n is not a quadratic residue mod sqrt(A)
    b = my_math.mod_sqrt(n, root_A)
    B = (b + (n - b*b) * my_math.mod_inv(b + b, root_A))%A

    # B*B-A*C = n <=> C = (B*B-n)/A
    C = (B*B - n) / A

    num_poly += 1

    # sieve for prime factors
    sums = [0.0]*(2*x_max)
    i = sp_idx
    for p in sieve_primes:
      logp = log_p[i]

      inv_A = my_math.mod_inv(A, p)
      # modular root of the quadratic
      a = int(((mod_root[i] - B) * inv_A)%p)
      b = int(((p - mod_root[i] - B) * inv_A)%p)

      amx = a+x_max
      bmx = b+x_max

      ax = amx-p
      bx = bmx-p

      k = p
      while k < x_max:
        sums[k+ax] += logp
        sums[k+bx] += logp
        sums[amx-k] += logp
        sums[bmx-k] += logp
        k += p

      if k+ax < x_max:  
        sums[k+ax] += logp
      if k+bx < x_max:
        sums[k+bx] += logp
      if amx-k > 0:
        sums[amx-k] += logp
      if bmx-k > 0:
        sums[bmx-k] += logp
      i += 1

    # check for smooths
    x = -x_max
    for v in sums:
      if v > thresh:
        vec = set()
        sqr = []
        # because B*B-n = A*C
        # (A*x+B)^2 - n = A*A*x*x+2*A*B*x + B*B - n
        #               = A*(A*x*x+2*B*x+C)
        # gives the congruency
        # (A*x+B)^2 = A*(A*x*x+2*B*x+C) (mod n)
        # because A is chosen to be square, it doesn't need to be sieved
        sieve_val = (A*x + B+B)*x + C

        if sieve_val < 0:
          vec = {-1}
          sieve_val = -sieve_val

        for p in prime:
          while sieve_val%p == 0:
            if p in vec:
              # keep track of perfect square factors
              # to avoid taking the sqrt of a gigantic number at the end
              sqr += [p]
            vec ^= {p}
            sieve_val = int(sieve_val / p)

        if sieve_val == 1:
          # smooth
          smooth += [(vec, (sqr, (A*x+B), root_A))]
          used_prime |= vec
        elif sieve_val in partial:
          # combine two partials to make a (xor) smooth
          # that is, every prime factor with an odd power is in our factor base
          pair_vec, pair_vals = partial[sieve_val]
          sqr += list(vec & pair_vec) + [sieve_val]
          vec ^= pair_vec
          smooth += [(vec, (sqr + pair_vals[0], (A*x+B)*pair_vals[1], root_A*pair_vals[2]))]
          used_prime |= vec
          num_partial += 1
        else:
          # save partial for later pairing
          partial[sieve_val] = (vec, (sqr, A*x+B, root_A))
      x += 1

    prev_num_smooth = num_smooth
    num_smooth = len(smooth)
    num_used_prime = len(used_prime)

    if verbose:
      print 100 * num_smooth / num_prime, 'percent complete\r',

    if num_smooth > num_used_prime and num_smooth > prev_num_smooth:
      if verbose:
        print '%d polynomials sieved (%d values)'%(num_poly, num_poly*x_max*2)
        print 'found %d smooths (%d from partials) in %f seconds'%(num_smooth, num_partial, time.time()-time1)
        print 'solving for non-trivial congruencies...'

      used_prime_list = sorted(list(used_prime))

      # set up bit fields for gaussian elimination
      masks = []
      mask = 1
      bit_fields = [0]*num_used_prime
      for vec, vals in smooth:
        masks += [mask]
        i = 0
        for p in used_prime_list:
          if p in vec: bit_fields[i] |= mask
          i += 1
        mask <<= 1

      # row echelon form
      col_offset = 0
      null_cols = []
      for col in xrange(num_smooth):
        pivot = col-col_offset == num_used_prime or bit_fields[col-col_offset] & masks[col] == 0
        for row in xrange(col+1-col_offset, num_used_prime):
          if bit_fields[row] & masks[col]:
            if pivot:
              bit_fields[col-col_offset], bit_fields[row] = bit_fields[row], bit_fields[col-col_offset]
              pivot = False
            else:
              bit_fields[row] ^= bit_fields[col-col_offset]
        if pivot:
          null_cols += [col]
          col_offset += 1

      # reduced row echelon form
      for row in xrange(num_used_prime):
        # lowest set bit
        mask = bit_fields[row] & -bit_fields[row]
        for up_row in xrange(row):
          if bit_fields[up_row] & mask:
            bit_fields[up_row] ^= bit_fields[row]

      # check for non-trivial congruencies
      for col in null_cols:
        all_vec, (lh, rh, rA) = smooth[col]
        lhs = lh   # sieved values (left hand side)
        rhs = [rh] # sieved values - n (right hand side)
        rAs = [rA] # root_As (cofactor of lhs)
        i = 0
        for field in bit_fields:
          if field & masks[col]:
            vec, (lh, rh, rA) = smooth[i]
            lhs += list(all_vec & vec) + lh
            all_vec ^= vec
            rhs += [rh]
            rAs += [rA]
          i += 1

        factor = my_math.gcd(my_math.list_prod(rAs)*my_math.list_prod(lhs) - my_math.list_prod(rhs), n)
        if 1 < factor < n:
          break
      else:
        if verbose:
          print 'none found.'
        continue
      break

  if verbose:
    print 'factors found:'
    print factor, 'x', n/factor
    print 'time elapsed: %f seconds'%(time.time()-time1)
  return factor

if __name__ == "__main__":
  import argparse
  parser = argparse.ArgumentParser(description='Uses a MPQS to factor a composite number')
  parser.add_argument('composite', metavar='number_to_factor', type=long, help='the composite number to factor')
  parser.add_argument('--verbose', dest='verbose', action='store_true', help="enable verbose output")
  args = parser.parse_args()

  if args.verbose:
    mpqs(args.composite, args.verbose)
  else:
    time1 = time.time()
    print mpqs(args.composite)
    print 'time elapsed: %f seconds'%(time.time()-time1)

my_math.pyঠিক একই পোস্ট থেকে নেওয়া হয়েছে mpqs.py, তবে আমি উত্তম প্রাইমগুলির মধ্যে সর্বাধিক ব্যবধানটি খুঁজে পেতে আমার উত্তরটিতে ব্যবহার করা আনবাউন্ডেড প্রাইম নম্বর জেনারেটরটিও যুক্ত করেছি ।

my_math.py

# primes less than 212
small_primes = [
    2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37,
   41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89,
   97,101,103,107,109,113,127,131,137,139,149,151,
  157,163,167,173,179,181,191,193,197,199,211]

# pre-calced sieve of eratosthenes for n = 2, 3, 5, 7
indices = [
    1, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47,
   53, 59, 61, 67, 71, 73, 79, 83, 89, 97,101,103,
  107,109,113,121,127,131,137,139,143,149,151,157,
  163,167,169,173,179,181,187,191,193,197,199,209]

# distances between sieve values
offsets = [
  10, 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6,
   6, 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 4,
   2, 4, 8, 6, 4, 6, 2, 4, 6, 2, 6, 6,
   4, 2, 4, 6, 2, 6, 4, 2, 4, 2,10, 2]

# tabulated, mod 105
dindices =[
  0,10, 2, 0, 4, 0, 0, 0, 8, 0, 0, 2, 0, 4, 0,
  0, 6, 2, 0, 4, 0, 0, 4, 6, 0, 0, 6, 0, 0, 2,
  0, 6, 2, 0, 4, 0, 0, 4, 6, 0, 0, 2, 0, 4, 2,
  0, 6, 6, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 4, 2,
  0, 6, 2, 0, 4, 0, 0, 4, 6, 0, 0, 2, 0, 6, 2,
  0, 6, 0, 0, 4, 0, 0, 4, 6, 0, 0, 2, 0, 4, 8,
  0, 0, 2, 0,10, 0, 0, 4, 0, 0, 0, 2, 0, 4, 2]

max_int = 2147483647


# returns the index of x in a sorted list a
# or the index of the next larger item if x is not present
# i.e. the proper insertion point for x in a
def binary_search(a, x):
  s = 0
  e = len(a)
  m = e >> 1
  while m != e:
    if a[m] < x:
      s = m
      m = (s + e + 1) >> 1
    else:
      e = m
      m = (s + e) >> 1
  return m


# divide and conquer list product
def list_prod(a):
  size = len(a)
  if size == 1:
    return a[0]
  return list_prod(a[:size>>1]) * list_prod(a[size>>1:])


# greatest common divisor of a and b
def gcd(a, b):
  while b:
    a, b = b, a%b
  return a


# extended gcd
def ext_gcd(a, m):
  a = int(a%m)
  x, u = 0, 1
  while a:
    x, u = u, x - (m/a)*u
    m, a = a, m%a
  return (m, x, u)


# legendre symbol (a|m)
# note: returns m-1 if a is a non-residue, instead of -1
def legendre(a, m):
  return pow(a, (m-1) >> 1, m)


# modular inverse of a mod m
def mod_inv(a, m):
  return ext_gcd(a, m)[1]


# modular sqrt(n) mod p
# p must be prime
def mod_sqrt(n, p):
  a = n%p
  if p%4 == 3:
    return pow(a, (p+1) >> 2, p)
  elif p%8 == 5:
    v = pow(a << 1, (p-5) >> 3, p)
    i = ((a*v*v << 1) % p) - 1
    return (a*v*i)%p
  elif p%8 == 1:
    # Shank's method
    q = p-1
    e = 0
    while q&1 == 0:
      e += 1
      q >>= 1

    n = 2
    while legendre(n, p) != p-1:
      n += 1

    w = pow(a, q, p)
    x = pow(a, (q+1) >> 1, p)
    y = pow(n, q, p)
    r = e
    while True:
      if w == 1:
        return x

      v = w
      k = 0
      while v != 1 and k+1 < r:
        v = (v*v)%p
        k += 1

      if k == 0:
        return x

      d = pow(y, 1 << (r-k-1), p)
      x = (x*d)%p
      y = (d*d)%p
      w = (w*y)%p
      r = k
  else: # p == 2
    return a


#integer sqrt of n
def isqrt(n):
  c = n*4/3
  d = c.bit_length()

  a = d>>1
  if d&1:
    x = 1 << a
    y = (x + (n >> a)) >> 1
  else:
    x = (3 << a) >> 2
    y = (x + (c >> a)) >> 1

  if x != y:
    x = y
    y = (x + n/x) >> 1
    while y < x:
      x = y
      y = (x + n/x) >> 1
  return x


# integer cbrt of n
def icbrt(n):
  d = n.bit_length()

  if d%3 == 2:
    x = 3 << d/3-1
  else:
    x = 1 << d/3

  y = (2*x + n/(x*x))/3
  if x != y:
    x = y
    y = (2*x + n/(x*x))/3
    while y < x:
      x = y
      y = (2*x + n/(x*x))/3
  return x


# strong probable prime
def is_sprp(n, b=2):
  if n < 2: return False
  d = n-1
  s = 0
  while d&1 == 0:
    s += 1
    d >>= 1

  x = pow(b, d, n)
  if x == 1 or x == n-1:
    return True

  for r in xrange(1, s):
    x = (x * x)%n
    if x == 1:
      return False
    elif x == n-1:
      return True

  return False


# lucas probable prime
# assumes D = 1 (mod 4), (D|n) = -1
def is_lucas_prp(n, D):
  P = 1
  Q = (1-D) >> 2

  # n+1 = 2**r*s where s is odd
  s = n+1
  r = 0
  while s&1 == 0:
    r += 1
    s >>= 1

  # calculate the bit reversal of (odd) s
  # e.g. 19 (10011) <=> 25 (11001)
  t = 0
  while s:
    if s&1:
      t += 1
      s -= 1
    else:
      t <<= 1
      s >>= 1

  # use the same bit reversal process to calculate the sth Lucas number
  # keep track of q = Q**n as we go
  U = 0
  V = 2
  q = 1
  # mod_inv(2, n)
  inv_2 = (n+1) >> 1
  while t:
    if t&1:
      # U, V of n+1
      U, V = ((U + V) * inv_2)%n, ((D*U + V) * inv_2)%n
      q = (q * Q)%n
      t -= 1
    else:
      # U, V of n*2
      U, V = (U * V)%n, (V * V - 2 * q)%n
      q = (q * q)%n
      t >>= 1

  # double s until we have the 2**r*sth Lucas number
  while r:
    U, V = (U * V)%n, (V * V - 2 * q)%n
    q = (q * q)%n
    r -= 1

  # primality check
  # if n is prime, n divides the n+1st Lucas number, given the assumptions
  return U == 0


## Baillie-PSW ##
# this is technically a probabalistic test, but there are no known pseudoprimes
def is_bpsw(n):
  if not is_sprp(n, 2): return False

  # idea shamelessly stolen from Mathmatica's PrimeQ
  # if n is a 2-sprp and a 3-sprp, n is necessarily square-free
  if not is_sprp(n, 3): return False

  a = 5
  s = 2
  # if n is a perfect square, this will never terminate
  while legendre(a, n) != n-1:
    s = -s
    a = s-a
  return is_lucas_prp(n, a)


# an 'almost certain' primality check
def is_prime(n):
  if n < 212:
    m = binary_search(small_primes, n)
    return n == small_primes[m]

  for p in small_primes:
    if n%p == 0:
      return False

  # if n is a 32-bit integer, perform full trial division
  if n <= max_int:
    p = 211
    while p*p < n:
      for o in offsets:
        p += o
        if n%p == 0:
          return False
    return True

  return is_bpsw(n)


# next prime strictly larger than n
def next_prime(n):
  if n < 2:
    return 2

  # first odd larger than n
  n = (n + 1) | 1
  if n < 212:
    m = binary_search(small_primes, n)
    return small_primes[m]

  # find our position in the sieve rotation via binary search
  x = int(n%210)
  m = binary_search(indices, x)
  i = int(n + (indices[m] - x))

  # adjust offsets
  offs = offsets[m:] + offsets[:m]
  while True:
    for o in offs:
      if is_prime(i):
        return i
      i += o


# an infinite prime number generator
def primes(start = 0):
  for n in small_primes[start:]: yield n
  pg = primes(6)
  p = pg.next()
  q = p*p
  sieve = {221: 13, 253: 11}
  n = 211
  while True:
    for o in offsets:
      n += o
      stp = sieve.pop(n, 0)
      if stp:
        nxt = n/stp
        nxt += dindices[nxt%105]
        while nxt*stp in sieve:
          nxt += dindices[nxt%105]
        sieve[nxt*stp] = stp
      elif n < q:
        yield n
      else:
        sieve[q + dindices[p%105]*p] = p
        p = pg.next()
        q = p*p


# true if n is a prime power > 0
def is_prime_power(n):
  if n > 1:
    for p in small_primes:
      if n%p == 0:
        n /= p
        while n%p == 0: n /= p
        return n == 1

    r = isqrt(n)
    if r*r == n:
      return is_prime_power(r)

    s = icbrt(n)
    if s*s*s == n:
      return is_prime_power(s)

    p = 211
    while p*p < r:
      for o in offsets:
        p += o
        if n%p == 0:
          n /= p
          while n%p == 0: n /= p
          return n == 1

    if n <= max_int:
      while p*p < n:
        for o in offsets:
          p += o
          if n%p == 0:
            return False
      return True

    return is_bpsw(n)
  return False

2

পাইথন 2 + প্রাইমফ্যাক 1.1

এটি পরীক্ষা করার জন্য আমার কাছে রাস্পবেরি পাই নেই।

from primefac import primefac

def HP(n):
    factors = list(primefac(n))

    #print n, factors

    if len(factors) == 1 and n in factors:
        return n

    n = ""
    for f in sorted(factors):
        n += str(f)
    return HP(int(n))

এটি অনলাইনে চেষ্টা করুন

primefacফাংশনের প্রতিটি মৌলিক উত্পাদকই আপনাকে একটি তালিকা ফেরৎ n। এর সংজ্ঞা অনুসারে, এটি কল করে isprime(n), যা পরীক্ষার বিভাগ, ইউলারের পদ্ধতি এবং মিলার-রবিন আদিমতার পরীক্ষার সংমিশ্রণ ব্যবহার করে। আমি প্যাকেজটি ডাউনলোড করার এবং উত্সটি দেখার পরামর্শ দিচ্ছি।

আমি n = n * 10 ** int(floor(log10(f))+1) + fস্ট্রিং কনটেনটেশনের পরিবর্তে ব্যবহার করার চেষ্টা করেছি , তবে এটি অনেক ধীর।


pip install primefacআমার জন্য কাজ করেছে, যদিও forkব্যাকগ্রাউন্ডে আইনের কারণে 65 এবং 80 উইন্ডোতে চালিত হবে না ।
primo

উৎস এ খুঁজছেন জন্য primefacছিল বেশ মজার, যেহেতু সঙ্গে মন্তব্য অনেক আছে TODOবাfind out why this is throwing errors
mbomb007

আমি ঠিক করেছি। লেখক আসলে আমার এমপিকিউ ব্যবহার করেন! ... কিছুটা সংশোধিত 551 লাইন # This occasionally throws IndexErrors.হ্যাঁ, কারণ তিনি চেকটি সরিয়েছেন যে ব্যবহৃত মৌলিক উপাদানগুলির চেয়ে আরও মসৃণতা রয়েছে।
প্রিমো

আপনার তাকে সাহায্য করা উচিত। :)
mbomb007

আমি যখন এই চ্যালেঞ্জটি শেষ করেছি তখন আমি সম্ভবত তার সাথে যোগাযোগ করব, আমি এমপিকিউসকে কিছুটা অনুকূল করার কাজ করার ইচ্ছা করি (ম্যাথমেটিকাকে হারিয়ে ফেলব, আমি কি ঠিক আছি?)।
প্রিমো

2

সি শার্প

using System;
using System.Linq;

public class Program
{
    public static void Main(string[] args) {

        Console.Write("Enter Number: ");

        Int64 n = Convert.ToInt64(Console.ReadLine());

        Console.WriteLine("Start Time: " + DateTime.Now.ToString("HH:mm:ss.ffffff"));
        Console.WriteLine("Number, Factors");

        HomePrime(n);

        Console.WriteLine("End Time: " + DateTime.Now.ToString("HH:mm:ss.ffffff"));
        Console.ReadLine();
    }

    public static void HomePrime(Int64 num) {
        string s = FindFactors(num);
        if (CheckPrime(num,s) == true) {
            Console.WriteLine("{0} is prime", num);
        } else {
            Console.WriteLine("{0}, {1}", num, s);
            HomePrime(Convert.ToInt64(RemSp(s)));
        }
    }

    public static string FindFactors(Int64 num) {
        Int64 n, r, t = num;
        string f = "";
        for (n = num; n >= 2; n--) {
            r = CalcP(n, t);
            if (r != 0) {
                f = f + " " + r.ToString();
                t = n / r;
                n = n / r + 1;
            }
        }
        return f;
    }

    public static Int64 CalcP(Int64 num, Int64 tot) {
        for (Int64 i = 2; i <= tot; i++) {
            if (num % i == 0) {
                return i;
            } 
        }
        return 0;
    }

    public static string RemSp(string str) {
        return new string(str.ToCharArray().Where(c => !Char.IsWhiteSpace(c)).ToArray());
    }

    public static bool CheckPrime(Int64 num, string s) {
        if (s == "") {
            return false;
        } else if (num == Convert.ToInt64(RemSp(s))) {
            return true;
        }
        return false;
    }

}

এটি পূর্ববর্তী কোডটির আরও একটি অপ্টিমাইজড সংস্করণ, কিছু অপ্রয়োজনীয় অপ্রয়োজনীয় অংশগুলি সরানো হয়েছে।

আউটপুট (আমার আই 7 ল্যাপটপে):

Enter Number: 16
Start Time: 18:09:51.636445
Number, Factors
16,  2 2 2 2
2222,  2 11 101
211101,  3 11 6397
3116397,  3 163 6373
31636373 is prime
End Time: 18:09:51.637954

অনলাইন পরীক্ষা


প্রাক-নির্ধারিত প্রাইমস / মানগুলির সাথে একটি অ্যারে তৈরি করার অনুমতি দেওয়া হয় না, আমি বিশ্বাস করি, যেহেতু এটি একটি স্ট্যান্ডার্ড লুফোল।
পি কেটিনোস

@ পি.ক্টিনোস আমিও তাই মনে করি ... যাইহোক এটি অন্তর্ভুক্ত করা খুব বড় হবে।
মারিও

1

পার্ল + এনথিয়োরি, এইচপি (80) পিসিতে 0.35 এস তে

হাতে রাস্পবেরি পাই নেই।

use ntheory ":all";
use feature "say";
sub hp {
  my $n = shift;
  while (!is_prime($n)) {
    $n = join "",factor($n);
  }
  $n;
}
say hp($_) for (16,20,64,65,80);

প্রাথমিকতা পরীক্ষাটি হ'ল ইএস বিপিএসডাব্লু, আরও বড় সংখ্যার জন্য একক র্যান্ডম-বেস এমআর। এই আকারে আমরা is_provable_prime(এন -1 এবং / বা ইসিপিপি) গতিতে কোন লক্ষণীয় পার্থক্য ছাড়াই ব্যবহার করতে পারি , তবে এটি আসল সুবিধা ছাড়াই> 300-সংখ্যার মানগুলির পরিবর্তিত হবে। ফ্যাক্টরিংয়ে আকারের উপর নির্ভর করে ট্রায়াল, পাওয়ার, রোহ-ব্রেন্ট, পি -১, এসকিউএফএফ, ইসিএম, কিউএস অন্তর্ভুক্ত রয়েছে।

এই ইনপুটগুলির জন্য এটি OEIS সাইটে চার্লসের পারী / জিপি কোডের মতো একই গতিতে চলে। ntheory ছোট সংখ্যার জন্য দ্রুত ফ্যাক্টরিং আছে, এবং আমার পি -1 এবং ইসিএম বেশ ভাল, কিন্তু QS দুর্দান্ত নয় তাই আমি আশা করব যে কোনও সময়ে পারী দ্রুততর হবে।


1
আমি খুঁজে পেয়েছি যে পি -1 দ্বারা পাওয়া কোনও উপাদানও পাওয়া গেছে - তাড়াতাড়ি - ইসিএম দ্বারা, সুতরাং আমি এটিকে বাদ দিয়েছি (উইলিয়ামস পি + 1 এর জন্য এটির সমান অধিকার)। সম্ভবত আমি এসকিউএফএফ যোগ করার চেষ্টা করব। উজ্জ্বল গ্রন্থাগার, বিটিডব্লিউ।
প্রিমো

1
এছাড়াও use feature "say";,।
প্রিমো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.