2012-08-03 26 views
5

के तहत जेनरेट करें, मुझे इसे पायथन में करने की आवश्यकता है। एक दी गई सूची एल है, इसमें 5000 से अधिक पूर्णांक तत्व हो सकते हैं। संख्याओं की संख्या, 20000 या उच्च हो सकती है। उत्पादन सूची, तरह से उठाया सभी 2 संख्या के संभावित रकम होना चाहिए,एक सीमा सूची से सभी संभावित संयोजनों को एक सीमा

l=[1,2,3,4,5,6,7,8,9] 
output 
1+1,1+2,1+3,1+4,1+5,1+6........... 
2+2,2+3,2+4....... 
......... 
....... 

2,3,4,5,6... like that 

मैं, इस कोड का उपयोग कर रहा हूँ अब के लिए ऐसा करने से, लेकिन यह धीमी है

l=listgen() 
p=[] 
for i in range(0,len(l)): 
    for j in range(i,len(l)): 
     k=l[i]+l[j] 
     if k not in p: 
      p.append(k) 
p.sort 
print(p) 

listgen() वह इनपुट है जो इनपुट सूची उत्पन्न करता है।

+1

उपयोग http://docs.python.org/library/itertools.html?highlight=itertools#itertools.combinations –

+0

आप सीमा से क्या मतलब है? योग, या इनपुट सूची की लंबाई पर एक सीमा? –

+1

sum.sorry पर सीमा मैंने उल्लेख नहीं किया है कि – Madushan

उत्तर

9

कुछ पुराने ढंग का अनुकूलन आप तेजी से कोड छोरों के लिए कई के साथ सूची comprehensions से grok में आसान है मिल सकता है: एक अतिरिक्त बोनस के रूप में

def sums(lst, limit): # prevent global lookups by using a function 
    res = set()   # set membership testing is much faster than lists 
    res_add = res.add # cache add method 
    for i, first in enumerate(lst): # get index and item at the same time 
     for second in lst[i:]:  # one copy operation saves n index ops. 
      res_add(first + second) # prevent creation/lookup of extra local temporary 
    return sorted([x for x in res if x < limit]) 

print sums(listgen(), 20000) 

, इस संस्करण psyco, cython के साथ खूबसूरती से अनुकूलित करेंगे , आदि।

अद्यतन: जब अन्य सुझावों (सीमा (5000) के साथ listgen की जगह को यह तुलना, मैं:।

mine:  1.30 secs 
WolframH: 2.65 secs 
lazyr:  1.54 secs (estimate based on OPs timings -- I don't have Python 2.7 handy) 
+0

मैं इसे आजमाने जा रहा हूं! – Madushan

+0

@Madushan मैंने आपके कोड को भी चलाने की कोशिश की, लेकिन इसमें बहुत लंबा लगा और मुझे प्रक्रिया को मारना पड़ा :-( – thebjorn

+0

साइको खान के साथ 0.7 सेकेंड तक चला गया :-) – thebjorn

3

संपादित करें: थिबॉर्न का कहना है कि उनके पास सबसे कुशल समाधान है, और मेरे अपने परीक्षण सहमत हैं, हालांकि मैंने अपने प्रदर्शन में थोड़ा सुधार किया है। उनका कोड पायथन संस्करण पर भी कम निर्भर है और ऐसा लगता है कि इष्टतमकरण के संबंध में बहुत अच्छी तरह से सोचा और समझाया गया है। आपको उसका जवाब स्वीकार करना चाहिए (और उसे उपरोक्त देना)।

itertools.combinations_with_replacement (पायथन 2.7 में जोड़ा गया) का उपयोग करें, और pset बनाएं।

तुम सिर्फ इतना है कि p एक set है, यह एक बड़ा फर्क होता कि आपके कोड में छोटे परिवर्तन की एक जोड़ी बनाते हैं:

def sums(lst, limit): 
    from itertools import combinations_with_replacement 
    p = set(x + y for x, y in combinations_with_replacement(listgen(), 2)) 
    return sorted([x for x in p if x < limit]) 

आपका कोड इस लाइन की वजह से धीमी है

L = listgen() 
p = set() 
for i in range(0, len(L)): 
    for j in range(i, len(L)): 
     p.add(L[i] + L[j]) 
print(sorted(p)) 

वैसे, अपने उदाहरण में इस लाइन

p.sort 

का कोई प्रभाव नहीं है। आपको वास्तव में इसे निष्पादित करने के लिए एक विधि को कॉल करना होगा, जैसे:

p.sort() 
+0

मुझे सीमा का उपयोग करने में सक्षम कैसे होना चाहिए? मुझे इससे अधिक संख्या नहीं चाहिए। – Madushan

+0

'l' एक खराब चर नाम है क्योंकि इसे' 1' से भ्रमित किया जा सकता है। – jamylak

+0

+1 ऐसा करना चाहिए मुझे लगता है कि – jamylak

2

संपादित करें: सीमा शामिल है (जो ओपी के कोड में नहीं था)।

a = set(x + y for x in l for y in l) 
print(sorted(x for x in a if x < limit)) 

भी यही कारण है कि एल्गोरिथ्म की जटिलता (तुम्हारा संभावित O (n^4) किसी सूची में सदस्यता परीक्षण की वजह से है) कम कर देता है।

+1

मुझे लगता है कि यह मेरे से अधिक समय लेगा। – Madushan

+0

@Madushan: आपको ऐसा क्या लगता है? मेरे परीक्षण में, यह आपके से लगभग 50 गुना तेज था। – WolframH

+0

यह सेट() हो सकता है लेकिन आप जो भी कर रहे हैं वह भी कर रहे हैं, है ना? (पूरी सूची में जा रहा है) * सूची निकालें। – Madushan

0

यदि सूची में दोहराए गए तत्व हो सकते हैं तो पहले से छुटकारा पाने के लिए यह एक बुद्धिमान विचार हो सकता है, उदा। सूची को एक सेट में परिवर्तित करके।

+0

इनपुट में कोई दोहराया गया आइटम नहीं है। मैंने इसे सुनिश्चित करने के लिए अन्य कोड अनुकूलित किया है। – Madushan

1

यदि इनपुट सूची सॉर्ट की गई है, तो आप सीमा तक पहुंचने पर भीतरी पाश से बाहर निकल सकते हैं। इसके अलावा, p एक सेट बनाएं।

lst=listgen() 
lst.sort() 
p=set() 
for i in range(0,len(lst)): 
    for j in range(i,len(lst)): 
     k=lst[i]+lst[j] 
     if k > limit: 
      break 
     p.add(k) 
p = sorted(p) 
print(p) 
+0

इनपुट सूची सॉर्ट की गई है। मैंने आपके द्वारा संशोधित संशोधन किया है। किसी भी तरह से यह अभी तक धीमा है। – Madushan

1

आप इस के लिए "NumPy" इस्तेमाल कर सकते हैं यह आप निश्चित रूप से देता है आवश्यक प्रदर्शन:

import numpy as np 

data = np.arange(5000) 
limit = 20000 
result = np.zeros(0,dtype='i4') 
for i in data: 
    result = np.concatenate((result,data[i]+data[i:])) 
    if len(result) >= limit: break 
result = result[:limit] 

संपादित करें: मैं सिर्फ महसूस किया कि सीमा पर है तत्वों की संख्या पर योग और नहीं। फिर कोड पढ़ना चाहिए:

EDIT2: और तार्किक त्रुटियां मिलीं। मेरे को सही सुझाव है:

for idx, x in np.ndenumerate(data): 
    result = np.concatenate((result,x+data[idx[0]:])) 
    if x + data[-1] >= limit: break 
result = result[result <= limit] 
+0

मैंने अभी तक कुछ भी नहीं के लिए NumPy का उपयोग नहीं किया है। हो सकता है कि यह शुरू करने का समय हो। धन्यवाद – Madushan

+0

अंतिम पंक्ति एक वाक्यविन्यास त्रुटि प्रतीत होती है (क्षमा करें, यह पता लगाने के लिए पर्याप्त संख्या में पर्याप्त नहीं है कि यह सही है या नहीं आपने सीमा को गलत तरीके से व्याख्या की है - अन्य उत्तरों देखें ...?) – thebjorn

+0

@thebjorn: बेशक - आप सही हैं - मैंने ब्रैकेट को भ्रमित कर दिया। इसे अभी सुधार लिया। धन्यवाद! –