Classificar itens com base na dependência

12

Objetivo

Classifique uma lista de itens, garantindo que cada item seja listado após suas dependências especificadas.

Entrada

Uma matriz de matrizes de números inteiros, em que cada número inteiro especifica o índice com base em 0 ou em 1 de outro item que esse item deve vir depois. A entrada pode ser uma matriz ou string ou qualquer outra coisa legível por humanos.

Por exemplo, uma entrada baseada em 0:

[
  [ 2 ],    // item 0 comes after item 2
  [ 0, 3 ], // item 1 comes after item 0 and 3
  [ ],      // item 2 comes anywhere
  [ 2 ]     // item 3 comes after item 2
]

Suponha que não haja dependências circulares, sempre há pelo menos um pedido válido.

Resultado

Os números em ordem de dependência. Uma ordem ambígua não precisa ser determinística. A saída pode ser uma matriz ou texto ou qualquer outra coisa legível por humanos.

Somente um pedido deve ser fornecido na saída, mesmo quando houver vários pedidos válidos.

As saídas possíveis para a entrada acima incluem:

[ 2, 3, 0, 1 ]
[ 2, 0, 3, 1 ]

Pontuação

Uma função ou programa que conclua isso no menor número de bytes ganha a glória da aceitação. O prazo é de 6 dias.

Mão-E-Comida
fonte
4
Isso é chamado de Classificação Topológica para os curiosos.
Robert Fraser
A entrada pode ser uma matriz ou string ou qualquer outra coisa legível por humanos Apenas para ter certeza: pode ser uma matriz 2D com zeros e uns, em que um indica dependência e zero indica dependência?
Luis Mendo
@ DonMuesli, desculpe pela resposta tardia, mas não. A ideia veio de dependências de código. Se você adicionou outro módulo de código, seria irresponsável ter que modificar módulos de código irrelevantes para declarar que não eram dependentes desse novo módulo.
Hand-E-Food
Isso faz totalmente sentido. Dennis não deveria ser o vencedor?
Luis Mendo
Sim ele é. Desculpe, tarde da noite estressante e correndo com base em suposições.
Hand-E-Food

Respostas:

3

Geléia, 8 bytes

ịÐL³ŒḊ€Ụ

Isso se baseia na abordagem de profundidade (não implementada) da resposta em Python do @ xnor .

Experimente online!

Como funciona

ịÐL³ŒḊ€Ụ  Main link. Input: A (list of dependencies)

 ÐL       Apply the atom to the left until a loop is reached, updating the left
          argument with the last result, and the right argument with the previous
          left argument.
ị         For each number in the left argument, replace it with the item at that
          index in the right argument.
   ³      Call the loop with left arg. A (implicit) and right arg. A (³).
    ŒḊ€   Compute the depth of each resulting, nested list.
       Ụ  Sort the indices of the list according to their values.
Dennis
fonte
Esses 8 caracteres seriam realmente 19 bytes?
Mão-E-Comida
@ Mão-E-Food Jelly usa uma codificação personalizada (não UTF 8), de modo que cada personagem é um byte
Luis Mendo
@ Mão-e-Comida Don Muesli está correto. O Jelly usa essa página de código por padrão, que codifica todos os caracteres que entende como um byte cada.
27516 Dennis
7

Pitão, 21 bytes

hf.A.e!f>xYTxkTbQ.plQ
                    Q  input
                   l   length of input array
                 .p    all permutations of [0, 1, ..., lQ-2, lQ-1]
hf                     find the first permutation for which...
    .e          Q        map over the input array with indices...
       f       b           find all elements in each input subarray where...
        >xYT                 index of dependency is greater than...
            xkT              index of item
      !                    check whether resulting array is falsy (empty)
  .A                     is the not-found check true for [.A]ll elements?

Teste:

llama@llama:~$ echo '[[2],[0,3],[],[2]]' | pyth -c 'hf.A.e!f>xYTxkTbQ.plQ' 
[2, 0, 3, 1]
Maçaneta da porta
fonte
7

Python 2, 73 bytes

l=input()
f=lambda n:1+sum(map(f,l[n]))
print sorted(range(len(l)),key=f)

Classifica os vértices pela contagem de descendentes, que fcalcula recursivamente. Se um vértice aponta para outro vértice, seus descendentes incluem o vértice pontudo e todos os descendentes desse vértice; portanto, há estritamente mais descendentes. Portanto, ele é colocado depois do vértice apontado na ordem, conforme desejado.

A contagem de descendentes de um vértice é uma para si, mais a contagem de descendentes de cada um de seus filhos. Observe que um descendente pode ser contado várias vezes se houver vários caminhos que levam a ele.

Também teria trabalhado para usar a profundidade em vez da contagem de descendentes

f=lambda n:1+max(map(f,l[n]))

exceto o maxprecisaria dar 0em uma lista vazia.

xnor
fonte
2
Belo algoritmo. Isso teria 12 bytes em Pyth e Jelly.
Dennis
4

Pitão, 19 bytes

hf!s-V@LQT+k._T.plQ

Experimente online: Demonstração

Explicação:

hf!s-V@LQT+k._T.plQ   implicit: Q = input list
               .plQ   all permutations of [0, 1, ..., len(Q)-1]
 f                    filter for permutations T, which satisfy:
      @LQT               apply the permutation T to Q
                         (this are the dependencies)
            ._T          prefixes of T
          +k             insert a dummy object at the beginning
                         (these are the already used elements)
    -V                   vectorized subtraction of these lists
   s                     take all dependencies that survived
  !                      and check if none of them survived
h                    print the first filtered permutation
Jakube
fonte
4

Bash, 35 bytes

perl -pe's/^$/ /;s/\s/ $. /g'|tsort

Exemplo de execução

A E / S é indexada 1. Cada matriz segue uma linha separada, com espaço em branco como separador de itens.

$ echo $'4\n1\n\n3\n1 3 2' # [[4], [1], [], [3], [1, 3, 2]]
4
1

3
1 3 2
$ bash tsort <<< $'4\n1\n\n3\n1 3 2'
3
4
1
2
5

Como funciona

tsort- sobre o qual aprendi na resposta do @ DigitalTrauma - lê pares de tokens, separados por espaços em branco, que indicam uma ordem parcial e imprime uma ordem total (na forma de uma lista classificada de todos os tokens exclusivos) que estende a ordem parcial acima mencionada.

Todos os números em uma linha específica são seguidos por um espaço ou um avanço de linha. A s/\s/ $. /gparte do comando Perl substitui esses caracteres de espaço em branco por um espaço, o número da linha e outro espaço, garantindo assim que cada n na linha k preceda k .

Finalmente, se a linha estiver vazia (ou seja, consistir apenas em um avanço de linha), ele adicionará s/^$/ /um espaço a ela. Dessa forma, a segunda substituição transforma uma linha vazia k em k k, certificando-se de que cada número inteiro ocorra pelo menos uma vez na sequência que é canalizada tsort.

Dennis
fonte
Certo, ok. Eu acho que você ficou tsortmelhor / mais rápido do que eu :) Obrigado pela explicação extra.
Digital Trauma
3

Bash + coreutils, 20 80

nl -v0 -ba|sed -r ':;s/(\S+\s+)(\S+) /\1\2\n\1 /;t;s/^\s*\S+\s*$/& &/'|tsort|tac

Entrada como linhas separadas por espaço, por exemplo:

2
0 3

2
  • nl adiciona índices baseados em zero a todas as linhas
  • sed divide listas de impedimentos em pares de dependências simples e torna dependências incompletas dependentes de si mesmas.
  • tsort faz o tipo topológico necessário
  • tac coloca a ordem inversa de saída

Ideone. Ideone com o testcase do @Dennis

Trauma Digital
fonte
2

Python 2, 143 118 116 bytes

Uma abordagem um pouco mais aleatória .

from random import*
l=input()
R=range(len(l))
a=R[:]
while any(set(l[a[i]])-set(a[:i])for i in R):shuffle(a)
print a

Editar% s:

  • consertou e também salvou alguns bytes também.
  • Salvo 2 bytes (obrigado @Dennis)
Hannes Karppila
fonte