Trouvez l'aire du plus petit rectangle pour contenir des carrés de tailles jusqu'à n

19

Il s'agit d'une question de séquence du type habituel, telle qu'elle est appliquée à la séquence OEIS A038666 . Autrement dit, effectuez l'une des opérations suivantes:

  • N'acceptez aucune ou aucune entrée, et sortez A038666 jusqu'à la mort thermique de l'univers.
  • Acceptez un entier positif en entrée et sortez le n ème terme de A038666 ou ses n premiers termes. (Si vous utilisez0 - au lieu de1 indexation, alors bien sûr, vous devez également sortir1en0entrée.)

Le n ème terme de A038666 est la plus petite aire parmi les rectangles qui contiennent des carrés non superposés de tailles 1×1,2×2,n×n si vous utilisez l'indexation1 .

Exemple:

Le rectangle de plus petite surface pouvant contenir des carrés non superposés de tailles 1×1 à 4×4 a des dimensions 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

Par conséquent, a(4)=7×5=35 ( 1 indexé).

De même, le rectangle de moindre surface contenant des carrés non superposés de tailles 1×1 à 17×17 a des dimensions 39×46 , donc a(17)=39×46=1794 ( 1 indexé).

msh210
la source

Réponses:

10

JavaScript (ES6), 172 octets

Suggestion de version plus lente mais plus courte suggérée par @JonathanAllan (économisant également 4 octets dans la réponse d'origine):

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)

Essayez-le en ligne!


Réponse originale,  209 183 178  174 174 octets

Renvoie le N ème terme de la séquence, indexé sur 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)

Essayez-le en ligne!

Commenté

Fonction d'assistance

Nous définissons d'abord une fonction d'assistance S qui appelle une fonction de rappel c pour n à 0 (toutes deux incluses) et s'arrête dès qu'un appel renvoie une valeur véridique.

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

Fonction principale

Nous commençons avec A=1 .

(w,h)w×h=A1×1n×n (en fait commençant par le plus grand) dans la zone correspondante, de telle manière qu'ils ne se chevauchent pas.

(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
la source
2
Économisez 6 * en ne définissant pas het en ne déplaçant pas le test a%w<1vers la fin du TIO de récursivité . Bien sûr, c'est beaucoup plus lent. (* au moins - je ne suis pas un expert JavaScript!)
Jonathan Allan
@JonathanAllan Merci. :) En fait, je me demande si a%w<1pourrait être remplacé par juste 1. Je vais devoir vérifier cela plus tard.
Arnauld
0

Python 2 (PyPy) , 250 236 octets

-14 octets grâce aux suggestions de msh210 .

Génère le nième terme indexé 1 de la séquence.

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

Essayez-le en ligne! Pour n> 4, cela prend beaucoup de temps. J'ai vérifié le résultat jusqu'à n = 7 localement.

ovs
la source
Pourriez-vous inclure une explication de son fonctionnement? En outre, j'imagine que vous pouvez raser les octets en indentant un espace à la fois au lieu de sept (pour la deuxième indentation). (En fait, je pense que peut-être les deux forlignes peuvent être sur une seule ligne, et vous n'avez besoin de mettre en retrait qu'une seule fois.)
msh210
1
@ msh210 les "7 espaces" sont en fait un onglet, comme en Python 2 vous pouvez d'abord mettre en retrait avec un espace, puis avec un onglet. Mettre les deux boucles for sur une seule ligne serait malheureusement une syntaxe invalide.
ArBo
1
@ msh210 J'ai trouvé une façon différente de combiner celles des boucles. Ces 7 espaces étaient uniquement en ligne, merci pour la capture. J'essaierai d'écrire une explication demain
ovs