最大nのサイズの正方形を含む最小の長方形の領域を見つける


19

これは、OEISシーケンスA038666に適用される通常のタイプのシーケンス質問です。つまり、次のいずれかを実行します。

  • 宇宙の熱死まで、入力をまったくまたはまったく受け入れず、A038666を出力します。
  • 入力として正の整数を受け入れ、A038666の番目の項またはその最初の項を出力します。(インデックス付けの代わりにを使用する場合、もちろん入力時に出力する必要があります。)nn0110

A038666 の番目の項は、インデックスを使用している場合、サイズが重複しない正方形を含む長方形の中で最小の領域です。n1×1,2×2,n×n1

例:

サイズの非重複正方形含有することができる最小面積の矩形介して寸法有し:1×14×47×5

4 4 4 4 3 3 3
4 4 4 4 3 3 3
4 4 4 4 3 3 3
4 4 4 4 2 2 1
x x x x 2 2 x

したがって、( -indexed)。a(4)=7×5=351

同様に、サイズの非重複正方形を含む最小領域の長方形介して寸法有するので、( -indexed)。1×117×17 39×46a(17)=39×46=17941

回答:


10

JavaScript(ES6)、172バイト

@JonathanAllanによって提案されたより遅いがより短いバージョンの提案(元の回答で4バイトも節約):

f=(n,A,S=(n,c)=>n>=0?c(n)||S(n-1,c):0)=>S(A,w=>(F=(l,n)=>n?S(w-n,x=>S(A/w-n,y=>l.some(([X,Y,W])=>X<x+n&X+W>x&Y<y+n&Y+W>y)?0:F([...l,[x,y,n]],n-1))):A%w<1)([],n))?A:f(n,-~A)

オンラインでお試しください!


オリジナル答え、 209の183 178  174バイト

シーケンスの番目の項を1インデックスで返します。N

f=(n,A,S=(n,c)=>n>=0?c(n)||S(n-1,c):0)=>S(A,w=>A%w?0:(F=(l,n)=>n?S(w-n,x=>S(A/w-n,y=>l.some(([X,Y,W])=>X<x+n&X+W>x&Y<y+n&Y+W>y)?0:F([...l,[x,y,n]],n-1))):1)([],n))?A:f(n,-~A)

オンラインでお試しください!

コメント済み

ヘルパー機能

最初に、コールバック関数を呼び出すヘルパー関数を定義しますScn0(両方を含む)と呼がtruthy値を返すとすぐに停止します。

S = (n, c) =>               // n = integer, c = callback function
  n >= 0 ?                  // if n is greater than or equal to 0:
    c(n) ||                 //   invoke c with n; stop if it's truthy
    S(n - 1, c)             //   or go on with n - 1 if it's falsy
  :                         // else:
    0                       //   stop recursion and return 0

主な機能

A=1

(w,h)w×h=A1×1n×n

(X,Y)Wl[ ]

AA+1

f = ( n,                    // n = input
      A ) =>                // A = candidate area (initially undefined)
S(A, w =>                   // for w = A to w = 0:
  A % w ?                   //   if w is not a divisor of A:
    0                       //     do nothing
  : (                       //   else:
    F = (l, n) =>           //     F = recursive function taking a list l[] and a size n
      n ?                   //       if n is not equal to 0:
        S(w - n, x =>       //         for x = w - n to x = 0
          S(A / w - n, y => //           for y = A / w - n to y = 0:
            l.some(         //             for each square in l[]
            ([X, Y, W]) =>  //             located at (X, Y) and of width W:
              X < x + n &   //               test whether this square is overlapping
              X + W > x &   //               with the new square of width n that we're
              Y < y + n &   //               trying to insert at (x, y)
              Y + W > y     //
            ) ?             //             if some existing square does overlap:
              0             //               abort
            :               //             else:
              F([ ...l,     //               recursive call to F:
                  [x, y, n] //                 append the new square to l[]
                ],          //
                n - 1       //                 and decrement n
              )             //               end of recursive call
          )                 //           end of iteration over y
        )                   //         end of iteration over x
      :                     //       else (n = 0):
        1                   //         success: stop recursion and return 1
    )([], n)                //     initial call to F with an empty list of squares
) ?                         // end of iteration over w; if it was successful:
  A                         //   return A
:                           // else:
  f(n, -~A)                 //   try again with A + 1

2
hテストを定義せずa%w<1、再帰TIOの末尾に移動しないことにより、6 *を節約します。もちろん、はるかに遅いです。(*少なくとも-私はJavaScriptの専門家ではありません!)
ジョナサンアラン

@JonathanAllanありがとう。:)実際には、a%w<1単にに置き換えることができるのだろうか1。後でもう一度確認する必要があります。
アーナルド

0

Python 2(PyPy)250 236バイト

msh210の提案のおかげで-14バイト。

シーケンスの1から始まるn番目の項を出力します。

n=input()
r=range
k=n*-~n*(n-~n)/6
m=k*k
for Q in r(m):
 P={0}
 for X in r(n,0,-1):P|=([x for x in[{(x+a,y+b)for a in r(X)for b in r(X)}for x in r(Q%k-X+1)for y in r(Q/k-X+1)]if not x&P]+[{0}])[0]
 if len(P)>k:m=min(Q%k*(Q/k),m)
print m

オンラインでお試しください!n> 4の場合、これには多くの時間がかかります。ローカルでn = 7までの結果を確認しました。


どのように機能するかの説明を含めていただけますか?また、7つ(2番目のインデント)の代わりに一度に1つのスペースをインデントすることでバイトを削ることができると思います。(実際には、2 for行を1行にすることができ、インデントする必要があるのは1回だけだと思います。)
msh210

1
@ msh210「7個のスペース」は実際にはタブです。Python2では、最初にスペースでインデントし、次にタブでインデントできます。残念ながら、2つのforループを1行に置くと、構文が無効になります。
ArBo

1
@ msh210これらのforループを組み合わせる別の方法を見つけました。これらの7つのスペースはオンラインのみで、キャッチのおかげです。私は説明明日を書くしようとします
OVS
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.