Yakut, 228 bayt * 21895 = 4992060
->n{a=(0..n*2).map{$b=' '*n}
g=0
m=n*2
(n**0.5).to_i.downto(1){|i|n%i<1&&(m=[m,n+h=n/i].min
g+=h+1
g<m+2?(a[g-h-1,1]=(1..h).map{?**i+$b}):(x=(m-h..m).map{|j|r=a[j].rindex(?*);r ?r:0}.max
(m-h+1..m).each{|j|a[j][x+2]=?**i}))}
a}
Yasadışı koddan birkaç değişiklik. Bunlardan m
en büyüğü , değişkenin anlamının en kareli dikdörtgenin yüksekliğinden en kareli dikdörtgenin yüksekliğine kadar değişmesidir n
.
Önemsiz olarak, büyük için sağda çok fazla gereksiz boşluk anlamına gelen *40
değiştirildi ; ve değiştirildiğinde hangi alt kısmında çizilen araçlar dikdörtgenler her zaman (sadece çarpanlara olan sayılar için yoksul ambalaj içinde bu sonuçlar ilk iki sütun özledim )*n
n
-2
0
(n/2)*2
açıklama
Sonunda buna geri dönmek için zaman buldum.
Belirli için n
en küçük alan en uzun dikdörtgen ikisi için yeterli alana sahip olmalıdır 1*n
ve squarest dikdörtgen x*y
. Her iki dikdörtgenin de uzun kenarları aynı yönde olacaksa, en iyi yerleşimin elde edilebileceği açıktır.
Dikdörtgenler arasındaki boşluk gereksinimini göz ardı ederek, toplam alanın ya (n+y)*x = (n+n/x)*x
ya olduğunu buluruz n*(x+1)
. Her iki durumda da, bu değerlendirir n*x + n
. Boşluk da dahil olmak üzere x
, dikdörtgenleri uç uca n
yerleştirirsek veya dikdörtgenleri yan yana yerleştirirsek fazladan bir şey eklememiz gerekir . Bu nedenle birincisi tercih edilir.
Bu (n+y+1)*x
, alan alanı için aşağıdaki alt sınırları verir :
n area
60 71*6=426
111 149*3=447
230 254*10=2540
400 421*20=8240
480 505*20=10100
Bu, aşağıdaki algoritmayı önerir:
Find the value (n+y+1) which shall be the field height
Iterate from the squarest rectangle to the longest one
While there is space in the field height, draw each rectangle, one below the other, lined up on the left border.
When there is no more space in the field height, draw the remaining rectangles, one beside the other, along the bottom border, taking care not to overlap any of the rectangles above.
(Expand the field rightwards in the rare cases where this is necessary.)
Aşağıdaki 71 * 8 = 568 çıktıyı veren 60 hariç, gerekli test senaryoları için tüm dikdörtgenleri yukarıda belirtilen alt sınırlar dahilinde almak mümkündür. Bu, en ince iki dikdörtgeni bir kare ve sonra yukarı doğru hareket ettirerek 60 * 9 = 540'a biraz geliştirilebilir, ancak tasarruf minimaldir, bu nedenle muhtemelen herhangi bir ekstra kod değmez.
10
12
15
20
30
60
******
******
******
******
******
******
******
******
******
******
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
*
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
*
*** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
Bu toplam 21895 alan verir.
Kod çözülmemiş kod
f=->n{
a=(0..n*2).map{' '*40} #Fill an array with strings of 40 spaces
g=0 #Total height of all rectangles
m=n #Height of squarest rectangle (first guess is n)
(n**0.5).to_i.downto(1){|i|n%i<1&&(puts n/i #iterate through widths. Valid ones have n%i=0. Puts outputs heights for debugging.
m=[m,h=n/i].min #Calculate height of rectangle. On first calculation, m will be set to height of squarest rectangle.
g+=h+1 #Increment g
g<n+m+2? #if the rectangle will fit beneath the last one, against the left margin
(a[g-h-1,1]=(1..h).map{'*'*i+' '*40}) #fill the region of the array with stars
: #else
(x=(n+m-h..n+m).map{|j|r=a[j].rindex('* ');r ?r:-2}.max #find the first clear column
(n+m-h+1..n+m).each{|j|a[j][x+2]='*'*i} #and plot the rectangle along the bottom margin
)
)}
a} #return the array
puts f[gets.to_i]