找到最小矩形的面积以包含最大为n的正方形


19

这是通常类型的序列问题,适用于OEIS序列A038666。也就是说,请执行以下任一操作:

  • 接受否或任何输入,并输出A038666,直到宇宙热死为止。
  • 接受一个正整数作为输入,并输出n A038666或其第一的第术语n条款。(如果使用0而不是1索引,则当然也必须10输入时输出。)

n A038666的任期个矩形是其中最小的区域包含大小的非重叠广场1×1,2×2,n×n如果你使用1 -indexing。

例:

可以包含大小为1×14×4非重叠正方形的最小面积矩形的尺寸为7×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

因此,a(4)=7×5=351索引)。

类似地,包含大小为1×117×17 非重叠正方形的最小面积矩形的尺寸为39×46,因此a(17)=39×46=17941索引)。

Answers:


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字节

返回序列的N项,以1为索引。

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)

在线尝试!

已评论

辅助功能

我们首先定义一个辅助函数S,该函数调用n0(包括两者)的回调函数c,并在调用返回真实值时立即停止。n0

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开始。

wHw×H=一种1个×1个ñ×ñ

我们通过其位置跟踪正方形列表Xÿw ^[ ]

一种一种+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可以用just代替1。我稍后必须再次检查。
Arnauld

0

Python 2(PyPy)250 236字节

-14个字节感谢msh210的建议。

输出序列的第一个索引的第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的结果。


您介意说明其工作原理吗?而且,我想您可以通过一次缩进一个空格而不是七个缩进来节省字节(第二个缩进)。(实际上,我认为两for行可以在一行上,您只需缩进一次即可。)
msh210

1
@ msh210中的“ 7个空格”实际上是一个制表符,就像在Python 2中一样,您可以先缩进一个空格,然后再缩进一个制表符。不幸的是,将两个for循环放在一行上将是无效的语法。
ArBo

1
@ msh210我发现了将循环的那些组合的另一种方法。那7个只在线的地方,谢谢。我会尝试写一个解释的明天
OVS
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.