2012-03-07 32 views
5

Bazı ev ödevlerimi yapmak için bazı hızlı ve kirli komut dosyaları üzerinde çalışıyorum ve bunlardan biri, tüm öğelerin toplamı olarak sabit uzunluktaki listeler aracılığıyla yineliyor belirli bir sabit. Her biri için, bazı ek kriterleri karşılayıp karşılamadıklarını kontrol edip başka bir listeye yapıştırıyorum.Belirli bir sayıya verilen bir sayı dizisi oluşturma

Ben toplamı kriterlerini karşılamak için bir yolunu ancak korkunç görünüyor ve burada öğretilebilir an bir çeşit var eminim:

# iterate through all 11-element lists where the elements sum to 8. 
for a in range(8+1): 
for b in range(8-a+1): 
    for c in range(8-a-b+1): 
    for d in range(8-a-b-c+1): 
    for e in range(8-a-b-c-d+1): 
    for f in range(8-a-b-c-d-e+1): 
     for g in range(8-a-b-c-d-e-f+1): 
     for h in range(8-a-b-c-d-e-f-g+1): 
     for i in range(8-a-b-c-d-e-f-g-h+1): 
     for j in range(8-a-b-c-d-e-f-g-h-i+1): 
      k = 8-(a+b+c+d+e+f+g+h+i+j) 
      x = [a,b,c,d,e,f,g,h,i,j,k] 
      # see if x works for what I want 
+0

'[itertools.product içinde vals için vals (aralık (8), tekrar = 11) ise toplamı (vals) == 8] 'daha güzel ancak çözelti daha ** çok ** yavaş olur. – eumiro

+0

+1 - Tekrarlayan kimya ödevlerinizi otomatikleştirmek için bir bilgisayar kullanma aksesuarı. –

+0

Benim içgörüm şu: 8 toplamı olan 11 tamsayıların bir listesi için, sayıların bir LOT sıfır olacak. Bunu yapmanın hızlı bir yolu, tam sayı toplamları 8 ile karşılaştırmaktır - örneğin 8, 1 + 7, 2 + 6, 3 + 5, 4 + 4, 1 + 1 + 6, 1 + 2 + 5 ... 've sonra sadece uygun sayıda sıfır olanlara izin verin. –

cevap

1

Listeler, sözlükbilgisel sırayla veren bir yinelemeli üreteçtir. exact'un True olarak ayrılması, istenen sonucun her bir top == limitinde olduğu anlamına gelir; ayarını False olarak ayarlamak 0 < = toplam < = limitine sahip tüm listeleri verir. Özyineleme, ara sonuçların üretilmesi için bu seçeneğin avantajından yararlanır.

def lists_with_sum(length, limit, exact=True): 
    if length: 
     for l in lists_with_sum(length-1, limit, False): 
      gap = limit-sum(l) 
      for i in range(gap if exact else 0, gap+1): 
       yield l + [i] 
    else: 
     yield [] 
1

Genel, özyinelemeli çözüm:

def get_lists_with_sum(length, my_sum): 
    if my_sum == 0: 
     return [[0 for _ in range(length)]] 

    if not length: 
     return [[]] 
    elif length == 1: 
     return [[my_sum]] 
    else: 
     lists = [] 
     for i in range(my_sum+1): 
      rest = my_sum - i 
      sublists = get_lists_with_sum(length-1, rest) 
      for sl in sublists: 
       sl.insert(0, i) 
       lists.append(sl) 

    return lists 

print get_lists_with_sum(11, 8) 
+0

Sadece bunu çalıştırmayı denedim. Ah benim, yavaş ... Belki de tam gelişmiş yineleme yerine bir yığın kullanan bir şeye dönüşebilir? –

+0

Elbette düşük değerlerde hedefleniyor. Verilen sayılar için kabul edilebilir olduğunu düşünüyorum. İçine bir önbellek oluşturmak muhtemelen yardımcı olacaktır çünkü argümanlar sık ​​sık tekrar edecektir. Yine de daha yüksek değerli argümanlar için olası kombinasyonların sayısı patlayacaktır. –

+0

'8,11' argümanlarıyla, onu öldürmeden önce birkaç dakika boyunca CPU'umu yeniden çizdim. OP'nin cevabı aslında çok hızlı (sadece * çirkin *.) –

İlgili konular