Найти область наименьшего прямоугольника, в которой должны содержаться квадраты размером до 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

Следовательно, ( -индексированный).a(4)знак равно7×5знак равно351

Аналогично, прямоугольник наименьшей площади, содержащий неперекрывающиеся квадраты размером от до имеет размеры , поэтому ( индексированный).1×117×17 39×46a(17)знак равно39×46знак равно17941

msh210
источник

Ответы:

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 которая вызывает функцию обратного вызова с для N до 0 (оба включены) и останавливается, как только вызов возвращает истинное значение.

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 .

(вес,час)вес×часзнак равноA1×1N×N

(Икс,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
источник
2
Сохраните 6 *, не определяя hи не перемещая тест для a%w<1хвоста рекурсии TIO . Конечно, это намного медленнее. (* по крайней мере - я не эксперт по JavaScript!)
Джонатан Аллан
@JonathanAllan Спасибо. :) На самом деле, интересно, a%w<1можно ли заменить просто так 1. Я должен перепроверить это позже.
Арно
0

Python 2 (PyPy) , 250 236 байт

-14 байт благодаря предложениям msh210 .

Вывод 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 локально.

овс
источник
Не могли бы вы включить объяснение того, как это работает? Кроме того, я полагаю, что вы можете сбрить байты, делая отступ по одному пробелу за раз вместо семи (для второго отступа). (На самом деле, я думаю, что, может быть, две forстроки могут быть на одной строке, и вам нужно сделать отступ только один раз.)
msh210
1
@ msh210 «7 пробелов» фактически являются табуляцией, так как в Python 2 вы можете сделать отступ сначала пробелом, а затем табуляцией. К сожалению, размещение двух циклов for в одной строке будет неверным синтаксисом.
АрБо
1
@ msh210 Я нашел другой способ объединить их для циклов. Те 7 мест, где только на линии, спасибо за улов. Я буду стараться писать объяснение завтра
овс