পাইথনে সংখ্যার সমস্ত উপাদান খুঁজে বের করার সর্বাধিক দক্ষ উপায় কোনটি?


142

পাইথন (২.7) এর একটি সংখ্যার সমস্ত কারণ খুঁজে বের করার জন্য কেউ আমাকে দক্ষ পদ্ধতি ব্যাখ্যা করতে পারেন?

আমি এটি করার জন্য একটি অ্যালগরিদম তৈরি করতে পারি, তবে আমি মনে করি এটি খারাপভাবে কোড করা হয়েছে এবং বিপুল সংখ্যক ফলাফল পেতে খুব বেশি সময় নেয়।


3
অজগর আমি জানি না। তবে এই পৃষ্ঠাটি সম্ভবত আপনার জন্য কার্যকর en.wikedia.org/wiki/Integer_factorization
স্ট্যান

3
কিভাবে ব্যবহার সম্পর্কে primefac? pypi.python.org/pypi/primefac
Zubo

উত্তর:


265
from functools import reduce

def factors(n):    
    return set(reduce(list.__add__, 
                ([i, n//i] for i in range(1, int(n**0.5) + 1) if n % i == 0)))

এটি একটি সংখ্যার খুব দ্রুত সমস্ত কারণকে ফিরিয়ে দেবে n

উপরের সীমা হিসাবে বর্গমূল কেন?

sqrt(x) * sqrt(x) = x। সুতরাং যদি দুটি কারণ একই হয় তবে তারা উভয়ই বর্গমূল। আপনি যদি একটি ফ্যাক্টর আরও বড় করেন তবে আপনাকে অন্য ফ্যাক্টরটি আরও ছোট করতে হবে। এর অর্থ এই যে দুটির মধ্যে একটি সর্বদা এর চেয়ে কম বা তার সমান হবে sqrt(x), সুতরাং দুটি মিলের কারণগুলির মধ্যে একটি আবিষ্কার করতে আপনাকে কেবল সেই বিন্দুটি অনুসন্ধান করতে হবে। তারপরে x / fac1আপনি এটি পেতে ব্যবহার করতে পারেন fac2

দ্য reduce(list.__add__, ...)সামান্য তালিকা নিচ্ছে [fac1, fac2]এবং তাদের দীর্ঘ তালিকাতে একত্রে যোগ দিচ্ছে।

[i, n/i] for i in range(1, int(sqrt(n)) + 1) if n % i == 0আয় কারণের একজোড়া যদি বাকি যখন আপনি ভাগ nছোট হয় শূন্য (এটা খুব বড় এক চেক করতে হবে না; এটা ঠিক পায় বিভাজক দ্বারা nছোট এক করে।)

set(...)বাইরে সদৃশ, যা শুধুমাত্র নিখুঁত স্কোয়ার ঘটে পরিত্রাণ করা হয়। কারণ n = 4, এটি 2দু'বার ফিরে আসবে , সুতরাং setসেগুলির মধ্যে একটি থেকে পরিত্রাণ পান।


1
আমি আমার কম্পিউটারে আলগোরিদিম একটি তালিকা থেকে এই কপি-পেস্ট, আমি encapsulate ছিল না sqrt- এটা সম্ভবত থেকে সামনে মানুষ সত্যিই পাইথন 3. সমর্থনকারী সম্পর্কে চিন্তা ছিল আমি মনে করি সাইটে আমি থেকে বুঝেছি এটি বিরুদ্ধে চেষ্টা __iadd__এবং এটা ছিল দ্রুততর । আমি কিছুটা x**0.5হলেও দ্রুত হওয়ার বিষয়ে কিছু মনে করি বলে মনে হয় sqrt(x)- এবং এটি সেভাবে আরও নির্বোধ।
13:30

7
আমি এর if not n % iপরিবর্তে 15% দ্রুত সম্পাদন করতে দেখে মনে হচ্ছেif n % i == 0
ডানসালমো

3
@sthzg আমরা চাই যে এটি একটি পূর্ণসংখ্যা ফেরত পাঠাবে, একটি ফ্লোট নয়, এবং পাইথন 3-তে /একটি ফ্লোট ফিরিয়ে দেবে যদিও উভয় যুক্তিই পূর্ণসংখ্যার এবং সেগুলি ঠিক বিভাজ্য, অর্থাৎ 4 / 2 == 2.0নয় 2
agf 7'15

7
আমি জানি এটি একটি পুরানো প্রশ্ন, তবে পাইথন 3.x এ আপনাকে from functools import reduceএই কাজটি করার জন্য যুক্ত করতে হবে।
বেনামে

5
@ ইউনসেন_াইডার: এটি ঠিক শোনাচ্ছে না। আপনি এটি ব্যাক আপ কিছু সরবরাহ করতে পারেন?
রাই-

55

@Agf দ্বারা উপস্থাপিত সমাধানটি দুর্দান্ত, তবে কেউ প্যারিটির জন্য পরীক্ষা করে একটি নির্বিচার বিজোড় সংখ্যার জন্য ~ 50% দ্রুত রান সময় অর্জন করতে পারে । যেহেতু বিজোড় সংখ্যার কারণগুলি সর্বদা স্বতন্ত্র থাকে তাই বিজোড় সংখ্যার সাথে কাজ করার সময় এগুলি পরীক্ষা করা প্রয়োজন হয় না।

আমি নিজেই প্রকল্পের এলার ধাঁধা সমাধান করতে শুরু করেছি। কিছু সমস্যা হিসাবে, দুটি নেস্টেড forলুপের ভিতরে একটি বিভাজক চেক বলা হয় এবং এই ফাংশনটির কার্য সম্পাদন অত্যাবশ্যক।

এএফএফ এর দুর্দান্ত সমাধানের সাথে এই বাস্তবতার সংমিশ্রণ, আমি এই ফাংশনটি শেষ করেছি:

from math import sqrt
def factors(n):
        step = 2 if n%2 else 1
        return set(reduce(list.__add__,
                    ([i, n//i] for i in range(1, int(sqrt(n))+1, step) if n % i == 0)))

তবে, অল্প সংখ্যায় (~ <100), এই পরিবর্তন থেকে অতিরিক্ত ওভারহেড ফাংশনটি বেশি সময় নিতে পারে।

গতি পরীক্ষা করার জন্য আমি কিছু পরীক্ষা চালিয়েছি। নীচে কোড ব্যবহার করা হয়। বিভিন্ন প্লট তৈরি করতে, আমি সেই X = range(1,100,1)অনুযায়ী পরিবর্তন করেছি ।

import timeit
from math import sqrt
from matplotlib.pyplot import plot, legend, show

def factors_1(n):
    step = 2 if n%2 else 1
    return set(reduce(list.__add__,
                ([i, n//i] for i in range(1, int(sqrt(n))+1, step) if n % i == 0)))

def factors_2(n):
    return set(reduce(list.__add__,
                ([i, n//i] for i in range(1, int(sqrt(n)) + 1) if n % i == 0)))

X = range(1,100000,1000)
Y = []
for i in X:
    f_1 = timeit.timeit('factors_1({})'.format(i), setup='from __main__ import factors_1', number=10000)
    f_2 = timeit.timeit('factors_2({})'.format(i), setup='from __main__ import factors_2', number=10000)
    Y.append(f_1/f_2)
plot(X,Y, label='Running time with/without parity check')
legend()
show()

এক্স = ব্যাপ্তি (1,100,1) এক্স = ব্যাপ্তি (1,100,1)

এখানে উল্লেখযোগ্য পার্থক্য নেই, তবে বড় সংখ্যার সাথে সুবিধাটি সুস্পষ্ট:

এক্স = ব্যাপ্তি (1,100000,1000) (কেবল বিজোড় সংখ্যা) এক্স = ব্যাপ্তি (1,100000,1000) (কেবল বিজোড় সংখ্যা)

এক্স = ব্যাপ্তি (2,100000,100) (কেবলমাত্র সংখ্যার) এক্স = ব্যাপ্তি (2,100000,100) (কেবলমাত্র সংখ্যার)

এক্স = ব্যাপ্তি (1,100000,1001) (বিকল্প প্যারিটি) এক্স = ব্যাপ্তি (1,100000,1001) (বিকল্প প্যারিটি)


28

Agf এর উত্তর সত্যিই বেশ দুর্দান্ত। আমি ব্যবহারটি এড়াতে এটি আবার লিখতে পারি কিনা তা দেখতে চেয়েছিলাম reduce()। এটিই আমি নিয়ে এসেছি:

import itertools
flatten_iter = itertools.chain.from_iterable
def factors(n):
    return set(flatten_iter((i, n//i) 
                for i in range(1, int(n**0.5)+1) if n % i == 0))

আমি এমন একটি সংস্করণও চেষ্টা করেছিলাম যাতে ট্র্যাফিক জেনারেটর ফাংশন ব্যবহার করা হয়:

def factors(n):
    return set(x for tup in ([i, n//i] 
                for i in range(1, int(n**0.5)+1) if n % i == 0) for x in tup)

আমি এটি গণনা দ্বারা সময়সীমা:

start = 10000000
end = start + 40000
for n in range(start, end):
    factors(n)

পাইথন এটি সংকলন করতে আমি একবার এটি চালিয়েছি, তারপরে এটি সময় (1) কমান্ডের অধীনে তিনবার চালিয়েছি এবং সবচেয়ে ভাল সময় রেখেছি।

  • সংস্করণ হ্রাস: 11.58 সেকেন্ড
  • এটির সংস্করণ সংস্করণ: 11.49 সেকেন্ড
  • কৌতুক সংস্করণ: 11.12 সেকেন্ড

নোট করুন যে ইটারটুলস সংস্করণটি একটি টিউপল তৈরি করছে এবং এটি ফ্ল্যাটেন_মিটার () এ দিচ্ছে। আমি যদি পরিবর্তে একটি তালিকা তৈরির জন্য কোডটি পরিবর্তন করি তবে এটি কিছুটা ধীর হয়ে যায়:

  • iterools (তালিকা) সংস্করণ: 11.62 সেকেন্ড

আমি বিশ্বাস করি যে কৌতুকপূর্ণ জেনারেটর ফাংশন সংস্করণ পাইথনের মধ্যে দ্রুততম। তবে এটি আমার পরিমাপের উপর ভিত্তি করে প্রায় 4% দ্রুত হ্রাস সংস্করণের চেয়ে খুব বেশি দ্রুত নয়।


2
আপনি "কৌতুকপূর্ণ সংস্করণ" সহজ করতে পারেন (অপ্রয়োজনীয় অপসারণ for tup in):factors = lambda n: {f for i in range(1, int(n**0.5)+1) if n % i == 0 for f in [i, n//i]}
jfs

11

অগ এর উত্তরের বিকল্প পন্থা:

def factors(n):    
    result = set()
    for i in range(1, int(n ** 0.5) + 1):
        div, mod = divmod(n, i)
        if mod == 0:
            result |= {i, div}
    return result

1
আপনি ডিভ, মোড অংশ ব্যাখ্যা করতে পারেন?
আদনান

3
divmod (x, y) আয় ((xx% y) / y, x% y), অর্থাৎ বিভাগের ভাগফল এবং বাকী।
c4757p

এটি সদৃশ উপাদানগুলি ভালভাবে পরিচালনা করে না - উদাহরণস্বরূপ 81 চেষ্টা করুন।
phkahler

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

আমি সমস্ত কিছু এক লাইনে ঠুকে দিয়েছি কারণ এএফএফ এর উত্তর তাই করেছে। আমি reduce()উল্লেখযোগ্যভাবে দ্রুত ছিল কিনা তা জানতে আগ্রহী ছিলাম, তাই আমি যেমন reduce()অংশটি করেছি ঠিক তেমনই অন্যান্য কিছু করেছি than পাঠযোগ্যতার জন্য, মত is_even(n)প্রকাশের চেয়ে ফাংশন কলটি দেখতে ভাল লাগবে n % 2 == 0
স্টিভাহ

9

এখানে @ অগফের সমাধানের বিকল্প রয়েছে যা একই অ্যালগরিদমকে আরও বেশি পাইথোনিক স্টাইলে প্রয়োগ করে:

def factors(n):
    return set(
        factor for i in range(1, int(n**0.5) + 1) if n % i == 0
        for factor in (i, n//i)
    )

এই সমাধানটি আমদানি ছাড়াই পাইথন 2 এবং পাইথন 3 উভয় ক্ষেত্রেই কাজ করে এবং আরও বেশি পাঠযোগ্য। আমি এই পদ্ধতির পারফরম্যান্স পরীক্ষা করিনি, তবে অ্যাসিপোটোটিকভাবে এটি একই হওয়া উচিত এবং যদি পারফরম্যান্স গুরুতর উদ্বেগজনক হয় তবে উভয়ই সমাধান অনুকূল নয়।


7

সেখানে SymPy নামক একটি শিল্প-শক্তি আলগোরিদিম factorint :

>>> from sympy import factorint
>>> factorint(2**70 + 3**80) 
{5: 2,
 41: 1,
 101: 1,
 181: 1,
 821: 1,
 1597: 1,
 5393: 1,
 27188665321L: 1,
 41030818561L: 1}

এটি এক মিনিটের মধ্যে নিল। এটি পদ্ধতির ককটেলগুলির মধ্যে স্যুইচ করে। উপরে লিঙ্কযুক্ত ডকুমেন্টেশন দেখুন।

সমস্ত মূল উপাদানগুলি দেওয়া, অন্যান্য সমস্ত কারণগুলি সহজেই তৈরি করা যায়।


দ্রষ্টব্য যে যদি স্বীকৃত উত্তরটিকে উপরের সংখ্যাটি ফ্যাক্ট করার জন্য পর্যাপ্ত পরিমাণে (অর্থাত্ একটি চিরন্তন) চালানোর অনুমতি দেওয়া হয়, তবে কিছু বড় সংখ্যক এটি ব্যর্থ হবে, যেমন নিম্নলিখিত উদাহরণটি। এটি ঝালর কারণে int(n**0.5)। উদাহরণস্বরূপ, যখন n = 10000000000000079**2, আমাদের আছে

>>> int(n**0.5)
10000000000000078L

যেহেতু 1000000000000000079 একটি প্রধান , তাই গৃহীত উত্তরের আলগোরিদিম কখনই এই উপাদানটি খুঁজে পাবে না। দ্রষ্টব্য যে এটি কেবল একের পর এক নয়; বড় সংখ্যার জন্য এটি আরও বেশি বন্ধ হয়ে যাবে। এই কারণে এই ধরণের অ্যালগরিদমে ভাসমান-পয়েন্ট সংখ্যাগুলি এড়ানো ভাল।


2
এটি সমস্ত বিভাজনকারীকে খুঁজে পায় না তবে কেবলমাত্র প্রাথমিক কারণগুলি এটি কোনও উত্তর নয়। আপনার দেখানো উচিত যে অন্যান্য সমস্ত কারণগুলি কীভাবে তৈরি করা যায়, কেবল এটি সহজেই বলা যায় না! যাইহোক, সিম্পি.ডিভিজাররা এই প্রশ্নের উত্তর দেওয়ার জন্য আরও ভাল ম্যাচ হতে পারে।
কলিন পিত্রাট

এবং নোট করুন যে সিম্পি.ডাইভিসরগুলি গৃহীত সমাধানের চেয়ে খুব দ্রুত নয়।
কলিন পিত্রাট

@ কলিনপিট্রাট: sympy.divisorsবিশেষত কয়েকটি বিভাজনকারী সংখ্যার জন্য আমি সন্দেহ করি যে এটি খুব দ্রুত নয়। কোন মানদণ্ড পেয়েছেন?
রাই-

আমি যখন এক বছর আগে এই মন্তব্যটি লিখেছিলাম তখনই রে আমি একটি কাজ করেছি। এটি লিখতে 2 মিনিট সময় লাগে তাই দ্বিগুণ চেক করুন।
কলিন পিটরত

3
@ কলিনপিট্রাট: চেক করা হয়েছে। যেমনটি প্রত্যাশিত, গৃহীত উত্তরটি প্রায় sympy.divisors১০,০০,০০০ এর মতো গতি এবং উচ্চতর কোনও কিছুর জন্য ধীর (যখন গতি আসলে গুরুত্বপূর্ণ)। (এবং, অবশ্যই, sympy.divisorsসংখ্যায় কাজ করে 10000000000000079**2))
রাই-

7

10 ** 16 অবধি এন এর জন্য (সম্ভবত আরও কিছুটা বেশি), এখানে একটি দ্রুত খাঁটি পাইথন 3.6 সমাধান রয়েছে,

from itertools import compress

def primes(n):
    """ Returns  a list of primes < n for n > 2 """
    sieve = bytearray([True]) * (n//2)
    for i in range(3,int(n**0.5)+1,2):
        if sieve[i//2]:
            sieve[i*i//2::i] = bytearray((n-i*i-1)//(2*i)+1)
    return [2,*compress(range(3,n,2), sieve[1:])]

def factorization(n):
    """ Returns a list of the prime factorization of n """
    pf = []
    for p in primeslist:
      if p*p > n : break
      count = 0
      while not n % p:
        n //= p
        count += 1
      if count > 0: pf.append((p, count))
    if n > 1: pf.append((n, 1))
    return pf

def divisors(n):
    """ Returns an unsorted list of the divisors of n """
    divs = [1]
    for p, e in factorization(n):
        divs += [x*p**k for k in range(1,e+1) for x in divs]
    return divs

n = 600851475143
primeslist = primes(int(n**0.5)+1) 
print(divisors(n))

6

আফগান এবং এরিকসনের সমাধানে আরও উন্নতি। নিম্নলিখিত কোডের টুকরোটি রান টাইম অ্যাসিপটোটিক জটিলতা পরিবর্তন না করে সমস্ত কারণের একটি বাছাই করা তালিকা প্রদান করে:

    def factors(n):    
        l1, l2 = [], []
        for i in range(1, int(n ** 0.5) + 1):
            q,r = n//i, n%i     # Alter: divmod() fn can be used.
            if r == 0:
                l1.append(i) 
                l2.append(q)    # q's obtained are decreasing.
        if l1[-1] == l2[-1]:    # To avoid duplication of the possible factor sqrt(n)
            l1.pop()
        l2.reverse()
        return l1 + l2

আইডিয়া: পরিবর্তে তালিকাটি সরবরাহ করার জন্য list.sort () ফাংশনটি ব্যবহারের পরিবর্তে এনলগ (এন) কে জটিলতা দেয়; L2 তে list.revers () ব্যবহার করা অনেক দ্রুত যা O (n) জটিলতা নেয়। (অজগরটি এভাবে তৈরি হয়)

লক্ষ্য করুন, l1 এর মধ্যে আই-এস রয়েছে যা বাড়ছে। l2 এ কিউ- গুলি রয়েছে যা হ্রাস পাচ্ছে। উপরোক্ত ধারণাটি ব্যবহার করার পিছনে কারণটি রয়েছে।


খুব নিশ্চিত list.reverseযে ও (এন) ও (1) নয়, এটি সামগ্রিক জটিলতা পরিবর্তন করে না।
agf

হ্যা, তা ঠিক. আমি একটি ভুল করেছিলাম. ও (এন) হওয়া উচিত। (আমি উত্তরটি এখনই
সঠিকটির

এটি @ স্টিভাহা বা @ অগফের সমাধানগুলির চেয়ে প্রায় 2 গুণ ধীর।
jfs

l1 + l2.reversed()তালিকায় স্থানটি পরিবর্তনের পরিবর্তে ফিরে এসে আপনি একটি ছোট (২-৩%) গতি উন্নতি করতে পারবেন ।
রাকুরাই

6

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

def factors(n):
    results = set()
    for i in xrange(1, int(math.sqrt(n)) + 1):
        if n % i == 0:
            results.add(i)
            results.add(int(n/i))
    return results

এটি যেমন লেখা আছে আপনাকে পরীক্ষা করার জন্য গণিত আমদানি করতে হবে, তবে গণিত.এসকিআরটি (এন) এর পরিবর্তে এন ** 5 এর কাজ করা উচিত। আমি সদৃশগুলির জন্য যাচাই করে সময় নষ্ট করা বিরক্ত করি না কারণ ডুপ্লিকেট নির্বিশেষে কোনও সেটে থাকতে পারে না।


দুর্দান্ত জিনিস! যদি আপনি int (math.sqrt (n)) + 1 এর জন্য লুপের বাইরে রাখেন তবে এর থেকে আরও কিছুটা পারফরম্যান্স পাওয়া উচিত কারণ এটি লুপের প্রতিটি পুনরাবৃত্তি পুনরায় গণনা করতে হবে না
ত্রিস্তান ফরোয়ার্ড

3
@ ত্রিস্তান ফরোয়ার্ড: পাইথনে লুপগুলি কীভাবে কাজ করবে তা নয়। xrange(1, int(math.sqrt(n)) + 1)একবার মূল্যায়ন করা হয়।
রাই-

5

এখানে হ্রাস ছাড়াই অন্য বিকল্প রয়েছে যা প্রচুর সংখ্যার সাথে ভাল সম্পাদন করে। এটি sumতালিকা সমতল করতে ব্যবহার করে।

def factors(n):
    return set(sum([[i, n//i] for i in xrange(1, int(n**0.5)+1) if not n%i], []))

1
এটি হয় না, এটি অসময়ে চতুর্ভুজ সময়। কোনও তালিকা ফ্ল্যাট করতে sumবা ব্যবহার reduce(list.__add__)করার জন্য ব্যবহার করবেন না ।
juanpa.arrivillaga

4

sqrt(number_to_factor)99 এর মতো অস্বাভাবিক সংখ্যার চেয়ে 3 টি বড় বড় সংখ্যাটি অবশ্যই ধরবেন যা 3 * 3 * 11 এবং floor sqrt(99)+1 == 10

import math

def factor(x):
  if x == 0 or x == 1:
    return None
  res = []
  for i in range(2,int(math.floor(math.sqrt(x)+1))):
    while x % i == 0:
      x /= i
      res.append(i)
  if x != 1: # Unusual numbers
    res.append(x)
  return res

1
এটি একটি সংখ্যার সমস্ত উপাদান তৈরি করে না। এটি একটি সংখ্যার প্রাথমিক কারণগুলি গণনা করে যেমন x=8প্রত্যাশার[1, 2, 4, 8][2, 2, 2]
:,

11 টি পাওয়া যায় যখন 9 এজিএফ দ্বারা প্রদত্ত কোডটিতে 9 টি সংযুক্ত হয়। `i = 9 -> 99% 9 == 0 -> 9 এবং 99/9 = 11 যোগ করা হয়েছে।
স্টিনিয়ার লিমা 0

4

একটি সংখ্যার গুণক খুঁজে বের করার সহজ উপায়:

def factors(x):
    return [i for i in range(1,x+1) if x%i==0]

2

আপনি যদি আরও দ্রুত যেতে প্রাইমস নম্বরটি ব্যবহার করতে চান তবে এখানে একটি উদাহরণ দেওয়া আছে। এই তালিকাগুলি ইন্টারনেটে সন্ধান করা সহজ। আমি কোডটিতে মন্তব্য যুক্ত করেছি।

# http://primes.utm.edu/lists/small/10000.txt
# First 10000 primes

_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, 223, 227, 229, 
        233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 
        283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 
        353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 
        419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 
        467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 
        547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 
        607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 
        661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 
        739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 
        811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 
        877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 
        947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 
# Mising a lot of primes for the purpose of the example
)


from bisect import bisect_left as _bisect_left
from math import sqrt as _sqrt


def get_factors(n):
    assert isinstance(n, int), "n must be an integer."
    assert n > 0, "n must be greather than zero."
    limit = pow(_PRIMES[-1], 2)
    assert n <= limit, "n is greather then the limit of {0}".format(limit)
    result = set((1, n))
    root = int(_sqrt(n))
    primes = [t for t in get_primes_smaller_than(root + 1) if not n % t]
    result.update(primes)  # Add all the primes factors less or equal to root square
    for t in primes:
        result.update(get_factors(n/t))  # Add all the factors associted for the primes by using the same process
    return sorted(result)


def get_primes_smaller_than(n):
    return _PRIMES[:_bisect_left(_PRIMES, n)]

আমি গিথুব এ একটি প্রকল্প তৈরি করেছি: github.com/Pierre-Tibault/Factor
পিয়েরে থিবল্ট

2

ইতিমধ্যে এখানে উপস্থাপিতগুলির চেয়ে সম্ভাব্যরূপে আরও দক্ষ অ্যালগরিদম (বিশেষত যদি সেখানে ছোট ছোট মৌলিক ফ্যাক্টন থাকে n)। এখানে কৌশলটি হ'ল সীমাটি সামঞ্জস্য করা যতক্ষণ না পরীক্ষামূলক বিভাগটি প্রতিবার প্রধান উপাদানগুলি খুঁজে পাওয়া যায়:

def factors(n):
    '''
    return prime factors and multiplicity of n
    n = p0^e0 * p1^e1 * ... * pk^ek encoded as
    res = [(p0, e0), (p1, e1), ..., (pk, ek)]
    '''

    res = []

    # get rid of all the factors of 2 using bit shifts
    mult = 0
    while not n & 1:
        mult += 1
        n >>= 1
    if mult != 0:
        res.append((2, mult))

    limit = round(sqrt(n))
    test_prime = 3
    while test_prime <= limit:
        mult = 0
        while n % test_prime == 0:
            mult += 1
            n //= test_prime
        if mult != 0:
            res.append((test_prime, mult))
            if n == 1:              # only useful if ek >= 3 (ek: multiplicity
                break               # of the last prime) 
            limit = round(sqrt(n))  # adjust the limit
        test_prime += 2             # will often not be prime...
    if n != 1:
        res.append((n, 1))
    return res

এটি অবশ্যই ট্রায়াল বিভাগ এবং আরও অভিনব কিছু নয়। এবং তাই এর দক্ষতায় এখনও খুব সীমাবদ্ধ (বিশেষত ছোট বিভাজক ছাড়াই বড় সংখ্যার জন্য)।

এটি অজগর 3; //অজগর 2 (যুক্ত from __future__ import division) এর জন্য খাপ খাইয়ে নেওয়া দরকার কেবল বিভাগটি should


1

ব্যবহারের set(...)ফলে কোডটি কিছুটা ধীর হয়ে যায় এবং আপনি যখন স্কোয়ার রুটটি পরীক্ষা করেন কেবল তখনই এটি প্রয়োজনীয়। আমার সংস্করণটি এখানে:

def factors(num):
    if (num == 1 or num == 0):
        return []
    f = [1]
    sq = int(math.sqrt(num))
    for i in range(2, sq):
        if num % i == 0:
            f.append(i)
            f.append(num/i)
    if sq > 1 and num % sq == 0:
        f.append(sq)
        if sq*sq != num:
            f.append(num/sq)
    return f

if sq*sq != num:যেখানে বর্গমূল একটি পূর্ণসংখ্যা নয়, কিন্তু বর্গমূল মেঝেতে একটি ফ্যাক্টর শর্ত 12, মত সংখ্যার জন্য প্রয়োজনীয়।

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

আমি এটি টাইপ করেছিলাম 10000 বার সমস্ত সংখ্যায় 1-200 এবং সমস্ত সংখ্যা 1-5000 এ 100 বার। এটি ডান্সালমো, জেসন শর্নস, অক্স্রোকস, এফএফস, স্টিভাহা এবং এরিকসনের সমাধান সহ আমি পরীক্ষা করা অন্যান্য সমস্ত সংস্করণকে ছাড়িয়ে যায়, যদিও অক্স্রক এর নিকটতমতম।


1

আপনার সর্বোচ্চ ফ্যাক্টরটি আপনার সংখ্যার চেয়ে বেশি নয়, তাই বলে নেওয়া যাক

def factors(n):
    factors = []
    for i in range(1, n//2+1):
        if n % i == 0:
            factors.append (i)
    factors.append(n)

    return factors

voila!


1
 import math

    '''
    I applied finding prime factorization to solve this. (Trial Division)
    It's not complicated
    '''


    def generate_factors(n):
        lower_bound_check = int(math.sqrt(n))  # determine lowest bound divisor range [16 = 4]
        factors = set()  # store factors
        for divisors in range(1, lower_bound_check + 1):  # loop [1 .. 4]
            if n % divisors == 0:
                factors.add(divisors)  # lower bound divisor is found 16 [ 1, 2, 4]
                factors.add(n // divisors)  # get upper divisor from lower [ 16 / 1 = 16, 16 / 2 = 8, 16 / 4 = 4]
        return factors  # [1, 2, 4, 8 16]


    print(generate_factors(12)) # {1, 2, 3, 4, 6, 12} -> pycharm output

 Pierre Vriens hopefully this makes more sense. this is an O(nlogn) solution. 

0

নিম্নলিখিত তালিকা বোধগম্য হিসাবে সাধারণ কিছু ব্যবহার করুন, উল্লেখ করে যে আমাদের 1 এবং যে সংখ্যাটি আমরা অনুসন্ধান করার চেষ্টা করছি তা পরীক্ষা করার দরকার নেই:

def factors(n):
    return [x for x in range(2, n//2+1) if n%x == 0]

বর্গমূলের ব্যবহারের প্রসঙ্গে, বলুন আমরা 10 এর গুণক খুঁজে পেতে চাই want sqrt(10) = 4সুতরাং এর পূর্ণসংখ্যার অংশ range(1, int(sqrt(10))) = [1, 2, 3, 4]এবং 4 পর্যন্ত স্পষ্টভাবে পরীক্ষা করা 5 স্পষ্টভাবে মিস করে।

যদি আমি কিছু অনুপস্থিত না করি তবে আমি আপনাকে পরামর্শ দেব, যদি আপনার অবশ্যই এটি ব্যবহার করা হয় int(ceil(sqrt(x)))। অবশ্যই এটি ফাংশনগুলিতে প্রচুর অপ্রয়োজনীয় কল উত্পাদন করে।


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

1
@ জেসন শকর্ন: আপনি 2 খুঁজে পেলে, আপনি তাত্ক্ষণিকভাবে জানতে পারবেন যে 10/2 = 5 পাশাপাশি বিভাজক, আলাদাভাবে 5 টি পরীক্ষা করার দরকার নেই! :)
মোবার্গ

0

আমি মনে করি পাঠ্যতা এবং গতির জন্য @ অক্স্রোকের সমাধানটি সবচেয়ে ভাল, সুতরাং পাইথন 3+ এর জন্য কোডটি আবার লিখে দেওয়া হয়েছে:

def num_factors(n):
    results = set()
    for i in range(1, int(n**0.5) + 1):
        if n % i == 0: results.update([i,int(n/i)])
    return results

0

আমি যখন এই প্রশ্নটি দেখেছি তখন আমি অবাক হয়ে গিয়েছিলাম যে আয়নার লুপগুলির চেয়ে দ্রুত আর্পী হলেও কেউই নিম্পি ব্যবহার করে না । @ অজিএফ এর সমাধানটি নিম্পির সাথে প্রয়োগ করে এবং এটি গড়ে 8x দ্রুত গতিতে পরিণত হয়েছিল । আমি বিশ্বাস করি যে আপনি যদি কিছু অন্যান্য সমাধানগুলি নিম্পে প্রয়োগ করেন তবে আপনি আশ্চর্যজনক সময় পেতে পারেন।

এখানে আমার ফাংশন:

import numpy as np
def b(n):
    r = np.arange(1, int(n ** 0.5) + 1)
    x = r[np.mod(n, r) == 0]
    return set(np.concatenate((x, n / x), axis=None))   

লক্ষ্য করুন যে এক্স-অক্ষের সংখ্যাগুলি ফাংশনের ইনপুট নয়। ফাংশনগুলিতে ইনপুটটি এক্স-অক্ষ বিয়োগের সংখ্যার 2 থেকে 2 হয় সুতরাং দশটি যেখানে ইনপুট হবে 2 ** 10-1 = 1023

লুপগুলির পরিবর্তে নমপি ব্যবহারের পারফরম্যান্স পরীক্ষার ফলাফল।


1
আপনি যদি কোনও লাইব্রেরি ব্যবহার করতে চলেছেন তবে এভগেনি সার্জিভের উত্তরে যেমনটি দেখা গেছে, সিমপ্যাই এটি সঠিকভাবে তৈরি করতে পারেন।
রাই-

0
import 'dart:math';
generateFactorsOfN(N){
  //determine lowest bound divisor range
  final lowerBoundCheck = sqrt(N).toInt();
  var factors = Set<int>(); //stores factors
  /**
   * Lets take 16:
   * 4 = sqrt(16)
   * start from 1 ...  4 inclusive
   * check mod 16 % 1 == 0?  set[1, (16 / 1)]
   * check mod 16 % 2 == 0?  set[1, (16 / 1) , 2 , (16 / 2)]
   * check mod 16 % 3 == 0?  set[1, (16 / 1) , 2 , (16 / 2)] -> unchanged
   * check mod 16 % 4 == 0?  set[1, (16 / 1) , 2 , (16 / 2), 4, (16 / 4)]
   *
   *  ******************* set is used to remove duplicate
   *  ******************* case 4 and (16 / 4) both equal to 4
   *  return factor set<int>.. this isn't ordered
   */

  for(var divisor = 1; divisor <= lowerBoundCheck; divisor++){
    if(N % divisor == 0){
      factors.add(divisor);
      factors.add(N ~/ divisor); // ~/ integer division 
    }
  }
  return factors;
}

এখানে প্রায় সমস্ত অ্যালগোরিদম * * .5 নম্বরের সীমার মধ্যে সীমাবদ্ধ তবে বাস্তবে এই পরিসরটি অনেক ছোট। এটি সংখ্যাটির আসলে স্কয়ার্ট। আমাদের যদি নিম্ন বিভাজক থাকে তবে আমরা তাকে সহজেই উপরেরটি পেতে পারি। যেহেতু এটির কেবল সংখ্যা / বিভাজক। ১ 16-এর জন্য আমি স্ক্যারিটির জন্য 4 পাই, তারপরে 1 থেকে 4 এ লুপ করব 2 যেহেতু 2 একটি 16 এর নিম্ন বদ্ধ বিভাজক হিসাবে আমরা 8 পেতে 16/2 নিই। যদি আমাদের 1 থাকে তবে 16 পেতে হবে (16/1)। প্রাইম ফ্যাক্টরিয়েশন সম্পর্কে শিখতে গিয়ে আমি এটি সামনে এলাম যাতে এটি অন্য কোথাও প্রকাশিত হয় কিনা তা আমি জানি না, তবে এটি বৃহত সংখ্যার জন্যও কাজ করে। আমি একটি অজগর সমাধান প্রদান করতে পারেন।
টাঙ্গাং আটঙ্গা

-4

আমি মনে করি এটি করার সহজ উপায়:

    x = 23

    i = 1
    while i <= x:
      if x % i == 0:
        print("factor: %s"% i)
      i += 1

আপনার উত্তর, সঠিক ফলাফল দেওয়ার সময়ও খুব অযোগ্য। গৃহীত উত্তরটি একবার দেখুন। এটি কীভাবে সমস্যার সমাধান করে তার একটি ব্যাখ্যা উত্তরকে আরও কার্যকর হতে সাহায্য করে।
নিক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.