フィールドに因子を適合させる


11

1000未満の正の整数を指定すると、その領域で可能なすべての長方形が表示されます。

仕事

入力が20であるとしましょう。20×1、10×2、または5×4の長方形を作成できるため、これは有効な出力です。

********************

**********
**********

*****
*****
*****
*****

考えられる各長方形は1回だけ表示されることに注意してください。

長方形は任意の順序、向き、または位置で表示されますが、2つの長方形が角であっても重なったり接触したりすることはありません。以下も有効です。

********************

            ****
**********  ****
**********  ****
            ****
            ****

得点

出力の境界ボックス領域(BBA)は、すべての長方形を囲む最小の長方形の領域です。最初の出力例では、サイズは20×9であるため、BBAは180です。2番目の出力例では、サイズは20×7であるため、BBAはわずか140です。

入力が60、111、230、400、および480の場合の出力のBBAを見つけて、それらを合計します。この合計にコードのサイズ(バイト単位)を掛けます。結果はあなたのスコアです。最低スコアが勝ちます。

ルール

  • プログラム(または関数)は、1000未満の正の整数に対して有効な出力を生成する必要があります。
  • 出力には、アスタリスク(*)、スペース()、および改行のみを含める必要があります。
  • 長方形の間に任意の量のスペースを置くことができますが、これはBBAにカウントされます。
  • 先頭または末尾の行または列がスペースのみの場合、BBAにはカウントされません。

特殊なケースをハードコーディングできますか?
カルビンの趣味

@ Calvin'sHobbiesはい、しかし、それが大いに役立つとは思いません。
Ypnypn

3
@ Calvin'sHobbiesフォルクスワーゲンのソリューション。
レベルリバーセント

回答:


3

ルビー、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)*xn*(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]


1

ルビー、56バイト

90385 * 56 = 5061560出力がMartinのものと同じであると仮定しています(そうだと思います)。

->n{1.upto(n){|i|i*i<=n&&n%i==0&&puts([?**(n/i)]*i,'')}}

便利なテストプログラムのもう1つの便利な機能を次に示します。

f=->n{1.upto(n){|i|i*i<=n&&n%i==0&&print(n/i,"*",i,"\n")};puts}

f[60];f[111];f[230];f[400];f[480]

これにより、参照用に次の出力が得られます。

60*1
30*2
20*3
15*4
12*5
10*6

111*1
37*3

230*1
115*2
46*5
23*10

400*1
200*2
100*4
80*5
50*8
40*10
25*16
20*20

480*1
240*2
160*3
120*4
96*5
80*6
60*8
48*10
40*12
32*15
30*16
24*20
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.