Tüm vektör bölümlerini verimli bir şekilde oluşturun


12

Bir vektör bölümü, bir vektörü, toplamları orijinal olacak şekilde bir dizi vektöre böler. İşte birkaç bölüm:

[3, 1, 2] = [3, 1, 2]
[3, 1, 2] = [0, 0, 1] + [0, 0, 1] + [0, 1, 0] + [1, 0, 0] + [2, 0, 0]
[3, 1, 2] = [1, 1, 2] + [2, 0, 0]

Burada vektör ekleme element olarak yapılır. Geçerli bir bölüm negatif tamsayılara sahip vektörler veya tamamen sıfır vektörü içermez.

Şimdi zorluk, hedef vektör verilen tüm olası vektör bölümlerini üreten bir program veya fonksiyon yazmaktır. Bu nispeten kolay gelebilir ...

... ama bir bükülme var. Giriş vektörü L boyutuna sahipse ve oluşturduğu en büyük bölüm M öğelerine sahipse, O (L * M) belleğinden fazlasını kullanamazsınız.

Bir tamsayı O (1) bellek kullandığını varsayabilirsiniz. Bu, bölümleri oluştururken çıktı almanız gerektiği anlamına gelir. Bunun da ötesinde, her bölümü yalnızca bir kez çıktılamanız gerekir. Örneğin, bunlar aynı bölümdür:

[3, 1, 2] = [3, 0, 2] + [0, 1, 0]
[3, 1, 2] = [0, 1, 0] + [3, 0, 2]

Her iki çıktıyı da çıkarırsanız, cevabınız geçersizdir.


Tüm bölümler [3, 2]:

[3, 2]
[0, 1] + [3, 1]
[0, 1] + [0, 1] + [3, 0]
[0, 1] + [0, 1] + [1, 0] + [2, 0]
[0, 1] + [0, 1] + [1, 0] + [1, 0] + [1, 0]
[0, 1] + [1, 0] + [2, 1]
[0, 1] + [1, 0] + [1, 0] + [1, 1]
[0, 1] + [1, 1] + [2, 0]
[0, 2] + [3, 0]
[0, 2] + [1, 0] + [2, 0]
[0, 2] + [1, 0] + [1, 0] + [1, 0]
[1, 0] + [2, 2]
[1, 0] + [1, 0] + [1, 2]
[1, 0] + [1, 1] + [1, 1]
[1, 1] + [2, 1]
[1, 2] + [2, 0]

Cevabınızı test etmek için çalıştırın [3, 2, 5, 2]. Her biri toplamı [3, 2, 5, 2]ve hepsi benzersiz olan 17939 bölümleri oluşturmalıdır (her bölümü ilk olarak sözlükbilimsel olarak sıralayarak benzersizliği test edebilirsiniz).


Bayt cinsinden en kısa kod kazanır.

Yanıtlar:


3

Python 2, 289 bayt

Basit kaba kuvvet algoritması. Tüm listeyi base max(input)+1( b) içinde sayı olarak ele alır ve aralıktaki her bir "sayıyı" kontrol [0, b**(L*M))edip etmediğini kontrol eder:

  1. Doğru tutarın toplamı
  2. Alfabetik sıraya göre (benzersizliği sağlar)

Liste bu ölçütlerle eşleşirse, program, sıfırı çıkaran tüm sıfır vektörlerle çıktı verir.

Hafıza kullanımı

Bu programda kullandığım en büyük veri yapısı, bellek vermek için Mliss uzunluğunu içeren bir liste uzunluğu olan çift iç içe bir listedir .LO(L*M)

Diğer veri yapılarım için 3 global ints O(3), 1 liste uzunluğu L( O(L)), 1 dizi uzunluğu M( O(M)) ve çıktı alırken en büyük dizinin bir kopyası var ( O(L*M)).

Toplamda, bu bana kriterleri yerine O(2*L*M + L + M + 3)getiren basitleştirilmiş bir bellek kullanımı O(L*M)sağlıyor.

Zaman karmaşıklığı

Kaba kuvvet algoritması olan bu algoritma son derece yavaştır. While döngüsünün sonlandırılması için dizideki son int'in olması gerekir b-1. Bunun b**(L*M)gerçekleşmeden önce döngünün çalışma süresi gerekir .

Ayrıca, liste her çalıştığında, L*M+L+Myinelemeleri kullanarak her iki koşulu da kontrol etmeli ve listeyi en kötü durumda yazdırmalıdır . Bu bir genel vermek için basitleştirir O(L*M * b**(L*M)). Programımı test etmeye çalıştım [3, 2, 5, 2], ancak 45 dakika sonra vazgeçtim.

Golf programı

v=input()
L=len(v)
M=sum(v)
b=max(v)
R=range
t=[L*[0]for i in R(M)]
def A(l,i):
 if i<L*M-1and~-b<l[i/L][i%L]:A(l,i+1)
 l[i/L][i%L]=-~l[i/L][i%L]%-~b
while t[-1][-1]<b:
 if v==[sum(q[i]for q in t)for i in R(L)]and all(`t[i]`>=`t[i+1]`for i in R(M-1)):print[x for x in t if[0]*L!=x]
 A(t,0)

Bu biraz daha golf olabilir, özellikle artış bölümü. Kod çözülmemiş kod geliyor.


Kesinlikle bu soruyu gönderdiğimde umduğum verimlilik değil, ama teknik olarak sorunu çözdüğünü tahmin ediyorum :)
orlp
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.