Elemente nach Abhängigkeit sortieren

12

Tor

Sortieren Sie eine Liste von Elementen, um sicherzustellen, dass jedes Element nach den angegebenen Abhängigkeiten aufgelistet wird.

Eingang

Ein Array von Arrays von Ganzzahlen, wobei jede Ganzzahl den auf 0 oder 1 basierenden Index eines anderen Elements angibt, nach dem dieses Element kommen muss. Die Eingabe kann ein Array oder eine Zeichenfolge oder alles andere sein, was für den Menschen lesbar ist.

Zum Beispiel eine 0-basierte Eingabe:

[
  [ 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
]

Angenommen, es gibt keine zirkulären Abhängigkeiten, es gibt immer mindestens eine gültige Reihenfolge.

Ausgabe

Die Zahlen in Abhängigkeitsreihenfolge. Eine mehrdeutige Reihenfolge muss nicht deterministisch sein. Die Ausgabe kann ein Array oder ein Text oder etwas anderes sein, das von Menschen gelesen werden kann.

In der Ausgabe sollte nur eine Bestellung angegeben werden, auch wenn es mehrere gültige Bestellungen gibt.

Mögliche Ausgaben für die obigen Eingaben sind:

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

Wertung

Eine Funktion oder ein Programm, das dies in der geringsten Anzahl von Bytes abschließt, gewinnt den Ruhm der Akzeptanz. Die Frist ist in 6 Tagen.

Hand-E-Food
quelle
4
Dies nennt man Topologische Sortierung für Neugierige.
Robert Fraser
Die Eingabe kann ein Array oder eine Zeichenfolge sein oder alles andere, was für den Menschen lesbar ist. Nur um sicherzugehen: Kann es ein 2D-Array mit Nullen und Einsen sein, wobei eine Abhängigkeit und eine Null keine Abhängigkeit anzeigt?
Luis Mendo
@DonMuesli, sorry für die verspätete Antwort, aber nein. Die Idee kam von Code-Abhängigkeiten. Wenn Sie ein weiteres Codemodul hinzufügen, ist es nicht zu verantworten, irrelevante Codemodule zu ändern, um zu erklären, dass sie nicht von diesem neuen Modul abhängig sind.
Hand-E-Food
Das macht total Sinn. Sollte Dennis nicht der Gewinner sein?
Luis Mendo
Ja, ist er. Entschuldigung, später stressiger Abend und Eile basierend auf Annahmen.
Hand-E-Food

Antworten:

3

Gelee, 8 Bytes

ịÐL³ŒḊ€Ụ

Dies basiert auf dem (nicht implementierten) Tiefenansatz von @ xnors Python-Antwort .

Probieren Sie es online!

Wie es funktioniert

ịÐ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
quelle
Wären diese 8 Zeichen tatsächlich 19 Bytes?
Hand-E-Food
@ Hand-E-Food Jelly verwendet eine benutzerdefinierte Codierung (nicht UTF 8), sodass jedes Zeichen ein Byte ist
Luis Mendo
@ Hand-E-Food Don Müsli stimmt. Jelly verwendet standardmäßig diese Codepage , die alle Zeichen codiert, die als jeweils ein Byte verstanden werden.
Dennis
7

Pyth, 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?

Prüfung:

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

Python 2, 73 Bytes

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

Sortiert die Eckpunkte nach der Anzahl ihrer Nachkommen, die frekursiv berechnet wird. Wenn ein Scheitelpunkt auf einen anderen Scheitelpunkt zeigt, enthalten seine Nachkommen den spitzen Scheitelpunkt und alle Nachkommen dieses Scheitelpunkts, sodass er streng mehr Nachkommen hat. Es wird also wie gewünscht später als der spitze Eckpunkt in der Reihenfolge platziert.

Die Anzahl der Nachkommen eines Scheitelpunkts ist eine für sich und die Anzahl der Nachkommen jedes seiner untergeordneten Elemente. Beachten Sie, dass ein Nachkomme mehrfach gezählt werden kann, wenn mehrere Pfade zu ihm führen.

Es hätte auch funktioniert, die Tiefe zu verwenden, anstatt die Anzahl der Nachkommen zu bestimmen

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

außer das maxmüsste man 0auf eine leere liste geben.

xnor
quelle
2
Schöner Algorithmus. Dies würde sowohl in Pyth als auch in Jelly 12 Bytes ergeben.
Dennis
4

Pyth, 19 Bytes

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

Probieren Sie es online aus: Demonstration

Erläuterung:

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
quelle
4

Bash, 35 Bytes

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

Beispiellauf

I / O ist 1-indiziert. Jedes Array wird in einer separaten Zeile mit Leerzeichen als Elementtrennzeichen angezeigt.

$ 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

Wie es funktioniert

tsort- was ich in der Antwort von @ DigitalTrauma erfahren habe - liest durch Leerzeichen getrennte Tokenpaare, die auf eine Teilreihenfolge hinweisen, und gibt eine Gesamtreihenfolge (in Form einer sortierten Liste aller eindeutigen Token) aus, die die oben genannte Teilreihenfolge erweitert.

Allen Zahlen in einer bestimmten Zeile folgt entweder ein Leerzeichen oder ein Zeilenvorschub. Der s/\s/ $. /gTeil des Perl-Befehls ersetzt diese Leerzeichen durch ein Leerzeichen, die Zeilennummer und ein anderes Leerzeichen, wodurch sichergestellt wird, dass jedes n in der Zeile k vor k steht .

Wenn die Zeile leer ist (dh nur aus einem s/^$/ /Zeilenumbruch besteht), wird ihr ein Leerzeichen vorangestellt. Auf diese Weise verwandelt die zweite Ersetzung eine leere Zeile k in k k, wobei sichergestellt wird, dass jede Ganzzahl mindestens einmal in der Zeichenfolge vorkommt, zu der eine Pipeline geleitet wird tsort.

Dennis
quelle
Richtig, ok. Ich denke, du hast tsortbesser / schneller gegriffen als ich :) Danke für die zusätzliche Erklärung.
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

Eingabe als durch Leerzeichen getrennte Zeilen, zB:

2
0 3

2
  • nl Fügt allen Zeilen nullbasierte Indizes hinzu
  • sed Teilt Abhängigkeitslisten in einfache Abhängigkeitspaare auf und macht unvollständige Abhängigkeiten von sich selbst abhängig.
  • tsort führt die erforderliche topologische Sortierung durch
  • tac Die Ausgabe erfolgt in umgekehrter Reihenfolge

Ideone. Ideone mit @Dennis 'Testfall

Digitales Trauma
quelle
2

Python 2, 143 118 116 Bytes

Ein etwas zufälligerer Ansatz.

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

Bearbeitungen:

  • reparierte es und sparte tatsächlich auch einige Bytes.
  • 2 Bytes gespeichert (danke @Dennis)
Hannes Karppila
quelle