Znajdź obszar najmniejszego prostokąta zawierający kwadraty o rozmiarach do n

19

Jest to pytanie sekwencyjne zwykłego typu, stosowane w odniesieniu do sekwencji OEIS A038666 . To znaczy wykonaj jedną z następujących czynności:

  • Nie akceptuj ani żadnych danych wejściowych i wysyłaj dane A038666 do śmierci cieplnej wszechświata.
  • Zaakceptuj dodatnią liczbę całkowitą jako dane wejściowe i wyślij ty składnik A038666 lub jego pierwsze składników . (W przypadku korzystania - zamiast -indexing, to oczywiście trzeba także wyjście na wejście).nn0110

th termin A038666 jest najmniej obszar między prostokątami, które zawierają nie nakładających się kwadratów wielkości , jeśli używasz -indexing.n1×1,2×2,n×n1

Przykład:

Prostokąt o najmniejszej powierzchni, który może zawierać nienakładające się kwadraty o rozmiarach od do ma wymiary :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

Dlatego ( -indexed).a(4)=7×5=351

Podobnie prostokąt o najmniejszej powierzchni zawierający nienakładające się kwadraty o rozmiarach do ma wymiary , więc ( -indexed).1×117×17 39×46a(17)=39×46=17941

msh210
źródło

Odpowiedzi:

10

JavaScript (ES6), 172 bajty

Sugerowana przez @JonathanAllan wolniejsza, ale krótsza wersja (również zapisująca 4 bajty w oryginalnej odpowiedzi):

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)

Wypróbuj online!


Oryginalna odpowiedź,  209 183 178  174 bajtów

Zwraca ty ciąg sekwencji, indeksowany 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)

Wypróbuj online!

Skomentował

Funkcja pomocnika

Najpierw definiujemy funkcję pomocniczą która wywołuje funkcję zwrotną dla do (obie zawarte) i zatrzymuje się, gdy wywołanie zwróci prawdziwą wartość.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

Główna funkcja

Zaczynamy od .A=1

Dla każdej pary tak, że , próbujemy wstawić wszystkie kwadraty o wielkości do (faktycznie zaczynając od największego) w odpowiednim obszarze, w taki sposób że się nie pokrywają.(w,h)w×h=A1×1n×n

Śledzimy listę kwadratów wraz z ich pozycją i ich szerokością w .(X,Y)Wl[ ]

Zwracamy jeśli znaleziono prawidłowe porozumienie, lub próbujemy ponownie z .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
źródło
2
Zaoszczędź 6 *, nie definiując hi nie przesuwając testu a%w<1do końca TIO rekurencji . Oczywiście jest znacznie wolniejszy. (* przynajmniej - nie jestem ekspertem od JavaScript!)
Jonathan Allan
@JonathanAllan Thanks. :) Właściwie zastanawiam się, czy a%w<1można go wymienić na just 1. Będę musiał to sprawdzić później.
Arnauld
0

Python 2 (PyPy) , 250 236 bajtów

-14 bajtów dzięki sugestiom msh210 .

Zwraca 1-indeksowy n-ty ciąg sekwencji.

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

Wypróbuj online! Dla n> 4 zajmuje to dużo czasu. Sprawdziłem wynik do n = 7 lokalnie.

ovs
źródło
Czy mógłbyś wyjaśnić, jak to działa? Wyobrażam sobie również, że możesz golić bajty, wcinając jedno miejsce na raz zamiast siedmiu (dla drugiego wcięcia). (W rzeczywistości myślę, że może dwie forlinie mogą znajdować się w jednej linii i wystarczy wcięcie tylko raz.)
msh210
1
@ msh210 „7 spacji” jest w rzeczywistości tabulacją, ponieważ w Pythonie 2 można wciąć najpierw spacją, a następnie tabulatorem. Umieszczenie dwóch pętli for w jednym wierszu byłoby niestety niepoprawną składnią.
ArBo
1
@ msh210 Znalazłem inny sposób na połączenie tych dla pętli. Te 7 miejsc, gdzie tylko on-line, dzięki za złapanie. Postaram się napisać wyjaśnienie jutro
OVS