Encontre a área do menor retângulo para conter quadrados de tamanhos até n

19

Esta é uma pergunta de sequência do tipo usual, aplicada à sequência OEIS A038666 . Ou seja, siga um destes procedimentos:

  • Aceite nenhuma ou nenhuma entrada e envie A038666 até a morte por calor do universo.
  • Aceitar um número inteiro positivo de entrada e de saída do n ésimo termo de A038666 ou os seus primeiros n termos. (Se estiver usando 0 - em vez de 1 indexação, é claro que você também precisará enviar 1na 0entrada.)

O n º prazo de A038666 é a área menos entre os retângulos que contêm quadrados não-sobrepostos de tamanhos 1×1,2×2,n×n se você estiver usando 1 -indexing.

Exemplo:

O retângulo de menor área que pode conter quadrados não sobrepostos dos tamanhos 1×1 a 4×4 tem dimensões 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

Portanto, a(4)=7×5=35 ( 1 indexado).

Da mesma forma, o retângulo de menor área que contém quadrados não sobrepostos dos tamanhos 1×1 a 17×17 possui dimensões 39×46 , então a(17)=39×46=1794 ( 1 indexado).

msh210
fonte

Respostas:

10

JavaScript (ES6), 172 bytes

Sugestão de versão mais lenta, porém mais curta, sugerida por @JonathanAllan (também economizando 4 bytes na resposta original):

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)

Experimente online!


Resposta original,  209 183 178  174 bytes

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)

Experimente online!

Comentado

Função auxiliar

Scn0

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

Função principal

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
Arnauld
fonte
2
Economize 6 * não definindo he movendo o teste para a%w<1a cauda do TIO de recursão . Claro que é muito mais lento. (* pelo menos - não sou especialista em JavaScript!)
Jonathan Allan
@JonathanAllan Thanks. :) Na verdade, eu me pergunto se a%w<1poderia ser substituído por apenas 1. Vou ter que verificar isso mais tarde.
Arnauld
0

Python 2 (PyPy) , 250 236 bytes

-14 bytes graças às sugestões do msh210 .

Gera o enésimo termo indexado 1 da sequência.

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

Experimente online! Para n> 4, isso leva muito tempo. Eu verifiquei o resultado até n = 7 localmente.

ovs
fonte
Você se importaria de incluir uma explicação de como isso funciona? Além disso, imagino que você possa raspar bytes recuando um espaço de cada vez, em vez de sete (para o segundo recuo). (Na verdade, acho que talvez as duas forlinhas possam estar em uma linha e você só precisa recuar uma vez.)
msh210
1
@ msh210 os "7 espaços" são de fato uma aba, pois no Python 2 você pode recuar primeiro com um espaço, depois com uma aba. Colocar os dois para loops em uma linha seria uma sintaxe inválida, infelizmente.
ArBo
1
@ msh210 Encontrei uma maneira diferente de combinar os loops. Esses 7 espaços onde apenas on-line, obrigado pela captura. Vou tentar escrever uma explicação amanhã
ovs