Empilhamento de caixas pesadas

27

Você tem um monte de caixas pesadas e deseja empilhá-las no menor número possível de pilhas. O problema é que você não pode empilhar mais caixas em uma caixa do que ela suporta, portanto, as caixas mais pesadas devem ficar no fundo de uma pilha.

O desafio

Entrada : uma lista de pesos de caixas, em kg inteiro.

Saída : uma lista de listas que descrevem as pilhas de caixas. Isso deve usar o menor número de pilhas possível para a entrada. Para ser uma pilha válida, o peso de cada caixa na pilha deve ser maior ou igual à soma do peso de todas as caixas acima dela.

Exemplos de pilhas válidas

(De baixo para cima)

  • [3]
  • [1, 1]
  • [3, 2, 1]
  • [4, 2, 1, 1]
  • [27, 17, 6, 3, 1]
  • [33, 32, 1]
  • [999, 888, 99, 11, 1]

Exemplos de pilhas inválidas

(De baixo para cima)

  • [1, 2]
  • [3, 3, 3]
  • [5, 5, 1]
  • [999, 888, 777]
  • [4, 3, 2]
  • [4321, 3000, 1234, 321]

Casos de teste de exemplo

1

IN: [1, 2, 3, 4, 5, 6, 9, 12]
OUT: [[12, 6, 3, 2, 1], [9, 5, 4]]

2

IN: [87, 432, 9999, 1234, 3030]
OUT: [[9999, 3030, 1234, 432, 87]]

3

IN: [1, 5, 3, 1, 4, 2, 1, 6, 1, 7, 2, 3]
OUT: [[6, 3, 2, 1], [7, 4, 2, 1], [5, 3, 1, 1]]

4

IN: [8, 5, 8, 8, 1, 2]
OUT: [[8, 8], [8, 5, 2, 1]]

Regras e premissas

  • Regras de E / S padrão e brechas proibidas se aplicam
  • Use qualquer formato conveniente para E / S
    • As pilhas podem ser descritas de cima para baixo ou de baixo para cima, desde que você seja consistente.
    • A ordem das pilhas (em vez das caixas dentro dessas pilhas) não importa.
    • Você também pode usar as caixas de entrada como uma lista predefinida. A ordem não é particularmente importante para a entrada, desde que o problema geral não esteja sendo resolvido pela própria classificação.
  • Se houver mais de uma configuração ideal de pilhas, você poderá produzir qualquer uma delas
  • Você pode assumir que há pelo menos uma caixa e que todas as caixas pesam pelo menos 1 kg
  • Você deve suportar pesos de até 9.999 kg, no mínimo.
  • Você deve suportar até 9.999 caixas totais, no mínimo.
  • Caixas com o mesmo peso são indistinguíveis, portanto, não há necessidade de anotar qual caixa foi usada onde.

Feliz golfe! Boa sorte!

Beefster
fonte
2
Podemos pegar os pesos em ordem ordenada? (ascendente ou descendente)
Arnauld
4
"Você deve suportar até 9.999 caixas totais, no mínimo." Como o "suporte" é interpretado aqui? Significa apenas que o programa deve ter tamanho tamanho de entrada ou significa que o programa deve realmente fornecer a resposta em um período de tempo razoável? Se for o último, devem ser fornecidos casos de teste muito maiores.
Joel
1
Caso de teste sugerido: [8, 8, 8, 5, 1]->[[8, 8], [8, 5, 1]]
Hiatsu
3
Ou ainda melhor: [8, 5, 8, 8, 1, 2]->[[8, 8], [8, 5, 2, 1]]
Hiatsu
2
@ Arnauld, pois caso contrário isso adicionaria código de classificação desinteressante a uma resposta, vou dizer que sim , você pode inserir as entradas na ordem de classificação.
Beefster

Respostas:

5

Geléia , 19 bytes

Œ!ŒṖ€ẎṖÄ>ḊƲ€¬ȦƊƇLÞḢ

Experimente online!

Óbvio -3 graças a Nick Kennedy ...

De cima para baixo.

Explicação:

Œ!ŒṖ€ẎṖÄ>ḊƲ€¬ȦƊƇLÞḢ  Arguments: S (e.g. [1, 2, 3, 4, 5])
Œ!                   Permutations (e.g. [..., [4, 1, 5, 2, 3], ...])
    €                Map link over left argument (e.g. [..., [..., [[4, 1], [5], [2, 3]], ...], ...])
  ŒṖ                  Partitions (e.g. [..., [[4, 1], [5], [2, 3]], ...])
     Ẏ               Concatenate elements (e.g. [..., ..., [[4, 1], [5], [2, 3]], ..., ...])
               Ƈ     Filter by link (e.g. [..., [[1, 3], [2], [4], [5]], ...])
              Ɗ       Create >=3-link monadic chain (e.g. [[1], [], [0]])
           €           Map link over left argument (e.g. [[1], [], [0]])
          Ʋ             Create >=4-link monadic chain (e.g. [1])
      Ṗ                  Remove last element (e.g. [4])
       Ä                 Cumulative sum (e.g. [4])
         Ḋ               [Get original argument] Remove first element (e.g. [1])
        >                Greater than (vectorizes) (e.g. [1])
            ¬          Logical NOT (vectorizes) (e.g. [[0], [], [1]])
             Ȧ         Check if non-empty and not containing zeroes after flattening (e.g. 0)
                 Þ   Sort by link (e.g. [[[1, 2, 3], [4, 5]], ..., [[5], [4], [3], [2], [1]]])
                L     Length (e.g. 4)
                  Ḣ  Pop first element (e.g. [[1, 2, 3], [4, 5]])
Erik, o Outgolfer
fonte
Alguma chance de uma versão menos compacta com explicação? Eu aprendo muito com eles.
John Keates
1
@JohnKeates Adicionado um.
Erik the Outgolfer
5

JavaScript (Node.js),  139 122  116 bytes

Espera a entrada classificada em ordem crescente.

f=(A,s=[],[n,...a]=A,r)=>n?s.some((b,i,[...c])=>n<eval(b.join`+`)?0:f(A,c,a,c[i]=[n,...b]))?S:r?0:f(A,[...s,[]]):S=s

Experimente online!

Comentado

f = (                        // f is a recursive function taking:
  A,                         //   A[] = input array
  s = [],                    //   s[] = list of stacks, initially empty
  [n,                        //   n   = next weight to process
      ...a] = A,             //   a[] = array of remaining weights
  r                          //   r   = recursion flag
) =>                         //
  n ?                        // if n is defined:
    s.some((b, i,            //   for each stack b[] at position i in s[],
                  [...c]) => //   using c[] as a copy of s[]:
      n < eval(b.join`+`) ?  //     if n is not heavy enough to support all values in b[]:
        0                    //       abort
      :                      //     else:
        f(                   //       do a recursive call:
          A, c, a,           //         using A[], c[] and a[]
          c[i] = [n, ...b]   //         with n prepended to c[i]
        )                    //       end of recursive call
    ) ?                      //   end of some(); if successful:
      S                      //     return S[]
    :                        //   else:
      r ?                    //     if this is a recursive call:
        0                    //       do nothing
      :                      //     else:
        f(A, [...s, []])     //       try again with an additional stack
  :                          // else:
    S = s                    //   success: save the solution in S[]
Arnauld
fonte
2

Python 3.8 (pré-lançamento) , 178 bytes

f=lambda b,s=[[]]:(a for i in range(len(s))if b[0]>=sum(s[i])for a in f(b[1:],s[:i]+[[b[0]]+s[i]]+s[i+1:]+[[]]))if b else[s]
g=lambda a:(c:=sorted(f(a),key=len)[0])[:c.index([])]

Experimente online!

Agora funciona em todas as entradas possíveis. (O tempo limite é excedido no TIO com mais de dez caixas, mas calcula uma resposta correta)

Hiatsu
fonte
2
list(reversed(sorted(a)))pode ser escrito como sorted(a)[::-1]para fins de golfe.
Joel
Você pensaria que eu já saberia disso, especialmente porque eu faço tantas outras indexações. Obrigado.
Hiatsu 30/08
Apenas como uma observação lateral, se não fosse para o golfe, seria melhor escrever sorted(a, reverse=True).
Joel