Ordina gli articoli in base alla dipendenza


12

Obbiettivo

Ordinare un elenco di elementi assicurando che ogni articolo sia elencato dopo le dipendenze specificate.

Ingresso

Un array di matrici di numeri interi, in cui ogni numero intero specifica l'indice in base 0 o in base 1 di un altro elemento che questo elemento deve seguire. L'input può essere un array o una stringa o qualsiasi altra cosa leggibile dall'uomo.

Ad esempio, un input basato su 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
]

Supponiamo che non ci siano dipendenze circolari, c'è sempre almeno un ordine valido.

Produzione

I numeri in ordine di dipendenza. Un ordine ambiguo non deve essere deterministico. L'output può essere un array o un testo o qualsiasi altra cosa leggibile dall'uomo.

È necessario fornire un solo ordine nell'output, anche in presenza di più ordini validi.

Le possibili uscite per l'ingresso sopra includono:

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

punteggio

Una funzione o un programma che completa questo nel minor numero di byte vince la gloria dell'accettazione. La scadenza è tra 6 giorni.


4
Questo si chiama ordinamento topologico per i curiosi.
Robert Fraser,

L'input può essere un array o una stringa o qualsiasi altra cosa leggibile dall'uomo Giusto per essere sicuri: può essere un array 2D con zeri e uno, dove uno indica dipendenza e zero indica nessuna dipendenza?
Luis Mendo,

@DonMuesli, scusate la risposta tardiva, ma no. L'idea è nata dalle dipendenze del codice. Se hai aggiunto un altro modulo di codice, sarebbe irresponsabile modificare i moduli di codice non pertinenti per dichiarare che non dipendevano da questo nuovo modulo.
Hand-E-Food

Questo ha perfettamente senso. Dennis non dovrebbe essere il vincitore?
Luis Mendo,

Si lo è. Scusate, tarda notte stressante e correndo sulla base di ipotesi.
Hand-E-Food

Risposte:


3

Gelatina, 8 byte

ịÐL³ŒḊ€Ụ

Questo si basa sull'approccio di profondità (non implementato) della risposta Python di @ xnor .

Provalo online!

Come funziona

ịÐ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.

Questi 8 caratteri sarebbero effettivamente 19 byte?
Hand-E-Food

@ Hand-E-Food Jelly utilizza una codifica personalizzata (non UTF 8), quindi ogni personaggio è un byte
Luis Mendo

@ Hand-E-Food Don Muesli è corretto. Jelly utilizza questa tabella codici per impostazione predefinita, che codifica tutti i caratteri che comprende come un byte ciascuno.
Dennis,

7

Pyth, 21 byte

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?

Test:

llama@llama:~$ echo '[[2],[0,3],[],[2]]' | pyth -c 'hf.A.e!f>xYTxkTbQ.plQ' 
[2, 0, 3, 1]

7

Python 2, 73 byte

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

Ordina i vertici in base al loro conteggio discendente, che f calcola in modo ricorsivo. Se un vertice punta a un altro vertice, i suoi discendenti includono il vertice appuntito e tutti i discendenti di quel vertice, quindi ha rigorosamente più discendenti. Quindi, viene inserito dopo il vertice appuntito nell'ordinamento, come desiderato.

Il conteggio discendente di un vertice è uno per sé, più il conteggio discendente di ciascuno dei suoi figli. Si noti che un discendente può essere contato più volte se vi sono più percorsi che conducono ad esso.

Avrebbe anche lavorato sulla profondità usata piuttosto che sul conteggio dei discendenti

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

tranne che maxavrebbe bisogno di dare 0su un elenco vuoto.


2
Bellissimo algoritmo. Ciò farebbe segnare 12 byte sia in Pyth che in Jelly.
Dennis,

4

Pyth, 19 byte

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

Provalo online: dimostrazione

Spiegazione:

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 byte

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

Esempio di esecuzione

L'I / O è 1 indicizzato. Ogni array passa su una riga separata, con spazi bianchi come separatore di elementi.

$ 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

Come funziona

tsort- di cui ho appreso nella risposta di @ DigitalTrauma - legge coppie di token, separate da spazi bianchi, che indicano un ordinamento parziale, e stampa un ordinamento totale (sotto forma di un elenco ordinato di tutti i token univoci) che estende il suddetto ordinamento parziale.

Tutti i numeri su una riga specifica sono seguiti da uno spazio o un avanzamento riga. La s/\s/ $. /gparte del comando Perl sostituisce quei caratteri di spazio bianco con uno spazio, il numero di riga e un altro spazio, assicurandosi così che ogni n sulla riga k preceda k .

Infine, se la linea è vuota (cioè consiste solo di un avanzamento riga), vi s/^$/ /antepone uno spazio. In questo modo, il secondo cambio trasforma una riga vuota k in k k, facendo in modo che ogni intero si verifica almeno una volta nella stringa che viene convogliato ad tsort.


Bene, ok Penso che tu abbia grugnito tsortmeglio / più velocemente di me :) Grazie per la spiegazione aggiuntiva.
Trauma digitale

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

Inserire come linee separate da spazio, ad es .:

2
0 3

2
  • nl aggiunge indici a base zero a tutte le linee
  • sed suddivide gli elenchi di dipendenza in semplici coppie di dipendenze e rende le dipendenze incomplete dipendenti da se stesse.
  • tsort fa l'ordinamento topologico richiesto
  • tac mette l'ordine inverso in uscita

Ideone. Ideone con la testcase di @Dennis


2

Python 2, 143 118 116 byte

Un approccio leggermente più casuale .

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

modifiche:

  • risolto il problema e salvato anche alcuni byte.
  • Salvato 2 byte (grazie @Dennis)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.