रूबी, 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
जिसका अर्थ है आयतों तल में साजिश रची हमेशा पहले दो कॉलम (संख्या जिसका केवल गुणन है के लिए गरीब पैकिंग में इस परिणाम को याद (n/2)*2
)
व्याख्या
मुझे आखिरकार इसे वापस पाने का समय मिल गया।
किसी दिए गए n
सबसे छोटे क्षेत्र में सबसे लंबी आयत 1*n
और चौकोर आयत दोनों के लिए पर्याप्त जगह होनी चाहिए 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 आउटपुट देता है। यह दो सबसे पतली आयतों को एक वर्ग और फिर ऊपर ले जाकर 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]