ルビー、228バイト* 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}
改変されていないコードからのいくつかの変更。最も大きいのm
は、正方形の長方形の高さから正方形の長方形の高さプラスまでの変数の意味の変化ですn
。
些細なことに*40
変更されまし*n
たが、これは大きな右側に多くの不要な空白を意味しn
ます。に-2
変更されます。0
これは、下部にプロットされた長方形が常に最初の2列を逃すことを意味します(これにより、因数分解のみが行われる数値のパッキングが低下します(n/2)*2
)。
説明
私はついにこれに戻る時間を見つけました。
与えられたためにn
、最小のフィールドは、最長の長方形の両方のための十分なスペース持っている必要があります1*n
し、squarest四角形をx*y
。両方の長方形の長辺が同じ方向を向いている場合、最適なレイアウトを実現できることは明らかです。
矩形間の空白の要件を無視して、私たちは、総面積はどちらかであることがわかります(n+y)*x = (n+n/x)*x
かn*(x+1)
。いずれにしても、これはと評価されn*x + n
ます。空白を含めてx
、長方形を端から端までn
配置する場合、または長方形を並べて配置する場合は、余分なものを含める必要があります。したがって、前者が望ましい。
これにより、(n+y+1)*x
フィールド領域に次の下限が与えられます。
n area
60 71*6=426
111 149*3=447
230 254*10=2540
400 421*20=8240
480 505*20=10100
これは、次のアルゴリズムを示唆しています。
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.)
実際には、上記の下限内で必要なテストケースのすべての四角形を取得することができますが、60を除き、次の71 * 8 = 568の出力が得られます。これは、最も細い2つの長方形を1正方形右に移動してから上に移動することで、わずかに60 * 9 = 540に改善できますが、保存は最小限であるため、余分なコードを追加する価値はおそらくありません。
10
12
15
20
30
60
******
******
******
******
******
******
******
******
******
******
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
*
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
*
*** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
これにより、合計面積は21895になります。
未ゴルフコード
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]