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.


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.

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]

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.


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

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.


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


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)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.