Bir listeyi bölümleyin!


10

Bu meydan okumada, bölümlerin maksimum boyut, minimum boyut ve tercih edilen bir boyuta sahip olduğu bir listeyi bölümlendirmeniz gerekir. Gösterimi (min,pref,max) bu meydan okumadaki boyutları belirtmek için kullanacağım.

Bölümlemeye aşina olmayanlar için, aşağıdaki liste 3 bölüme ayrılmıştır:
[0..9] -> [[0,1,2],[3,4,5],[6,7,8]]

Liste kalansız olduğunda, bölümleri mümkün olduğunca tercih boyutuna yakın olarak olması gerekir: [0..10], (2,4,5) -> [[0,1,2,3],[4,5,6],[7,8,9]]. Bu bölümleme, tercih [[0,1,2,3],[4,5,6,7],[8,9]]edilen uzunluktan daha fazlasına sahip olmasına rağmen tercih edilir. Resmi olarak, (partitionLength-preferredSize)^2her bölüm için toplamı en aza indirmeliyiz .

Bölüm uzunluklarının sırası önemli değildir: [0..5], (2,3,3)ya [[0,1,2],[3,4]]da [[0,1],[2,3,4]]çalışır. Hiçbir bölüm mümkün değilse, boş bir dizi döndürür: [0..7], (4,4,5) -> [].

Bunu 1<=min<=pref<=maxve size iletilen dizinin boş olmayan bir tamsayı dizisi olduğunu varsayabilirsiniz . Dizi her zaman ilk argüman olacaktır. Min, maks ve pref'yi herhangi bir sırada ve bir demet olarak veya ayrı bağımsız değişkenler olarak kabul edebilirsiniz.

Programınız birkaç saniye içinde çalışmalıdır. Temel olarak, sınırlar içindeki olası her bölüm boyutunun yinelenmesine izin verilmez.

Test senaryoları:

[1], (1,3,4)         -> [[1]]
[100], (1,2,3)       -> [[100]]
[1,2], (1,1,2)       -> [[1],[2]]
[1,2], (1,2,2)       -> [[1,2]]
[1,2], (1,3,3)       -> [[1,2]]
[1,2,3], (1,2,3)     -> [[1,2],[3]] or [[1,2,3]]
[1,2,3,4], (1,3,4)   -> [[1,2,3,4]]
[1,2,3,4,5], (3,3,4) -> []
[1,2,3,4,5], (2,2,2) -> []
[1,2,3,4,5], (3,3,5) -> [[1,2,3,4,5]]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49], (2,6,6) -> [[1,2,3,4,5,6],[7,8,9,10,11,12],[13,14,15,16,17,18],[19,20,21,22,23,24],[25,26,27,28,29],[30,31,32,33,34],[35,36,37,38,39],[40,41,42,43,44],[45,46,47,48,49]]

Bu bir , bu yüzden en sevdiğiniz dilde mümkün olduğunca az bayt hedefleyin!


Kullandığınız gösterim, [a..b]içerir ave hariç tutar b, doğru mu?
Alex

Kapsayıcı, B'ye özel.
Nathan Merrill

A hakkındaki yorumunuzun küme teorisinden bir bölümle aynı olmadığını unutmayın ...
agtoever

Ama bir tamsayı bölme etkili eşdeğer.
Nathan Merrill

Çözüm yoksa ne olur?
feersum

Yanıtlar:


2

Haskell, 152

_%0=[]
s%k|(a,b)<-splitAt(div(z s)k)s=a:b%(k-1)
z=length
f s n p x=snd$minimum$(z s*p^2,[]):[(sum[(z x-p)^2|x<-s%k],s%k)|k<-[-div(-z s)x..div(z s)n]]

Herhangi bir bölümde, uzunlukları iki veya daha fazla farklılık gösteren iki liste varsa, daha büyük listeyi küçültmek ve daha küçük listeyi büyütmek her zaman yararlı olacaktır. bu nedenle, hesaplamayı basitleştiren yalnızca iki liste boyutuna sahip bölümleri dikkate almamız gerekir.

program daha sonra bölümdeki olası tüm listeler üzerinde çalışır. bölümdeki liste miktarı göz önüne alındığında, puan benzersiz bir şekilde belirlenir. program uygun bir bölüm ve puanını hesaplar.

o zaman toplamı bulur ve döndürür.

Kullanım: giriş gibi f [1,2,3,4,5] 1 3 4( fmeydan okumayı çözen işlevdir)

En iyi seçeneği tamamen sayısal olarak hesaplamak ve ancak listeyi buna göre bölümlere ayırmak mümkün olsa da, çok fazla bayt aldı. Ancak, bu yaklaşımın son sürümü:

_%0=[]
s%k|(a,b)<-splitAt(div(length s)k)s=a:b%(k-1)
f s n p x|l<-length s=(s%)$snd$minimum$(l*p^2,0):[(k*j^2+mod l k*(1-2*j),k)|k<-[1..div l n],k*x>=l,j<-[p-div l k]]

1

CJam, 70

q~:S;_,[0L]a{_S2=e<),S0=>f{[__S1=-_*\]@@-j.+}[esL]a+:e<}j1={/(\e_}/;]p

Çevrimiçi deneyin

Kod, dinamik programlama kullanarak (kaydedilmiş özyineleme yoluyla) liste boyutuna göre en uygun bölüm boyutları dizisini bulur, ardından devam eder ve listeyi bölümler.

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.