Finde alle möglichen Permutationen mit Ruby und Rekursion

8

Ich habe versucht, eine einfache Quizfrage zu lösen, um alle möglichen Permutationen einer Zeichenkette mit Ruby und Rekursion zu finden.

Ich habe den folgenden Ruby-Code:

%Vor%

Immer wenn ich versuche, den Code mit puts permutation ("abc") zu testen bekomme ich folgende Ausgabe:

%Vor%

Theoretisch sollte es ein sehr einfaches und unkompliziertes Problem sein, aber ich bin mir sicher, dass ich etwas falsch mache. Höchstwahrscheinlich ist es etwas mit den Bereichen der Schleifen. Und ich weiß, dass die Ruby-Array-Klasse eine Instanzmethode Permutation hat, um das zu tun, aber ich versuche sie zu lösen, um sie zu üben.

Bitte beachten Sie, dass die Komplexität für die aktuelle Implementierung O (N!) ist. Gibt es trotzdem eine Verbesserung der Leistung?

    
Eki Eqbal 10.08.2014, 00:12
quelle

2 Antworten

10

Um zu sehen, was die Schwierigkeit sein könnte, versuchen wir es mit einem noch einfacheren Beispiel:

%Vor%

Ihr gewünschtes Ergebnis ist ["ab", "ba"] . Mal sehen, was du bekommst:

%Vor%

, so dass wir nicht zurückkommen, wenn

%Vor%

wird ausgeführt.

Als nächstes berechnen wir:

%Vor%

Beachten Sie, dass eine direktere Vorgehensweise für diese Berechnung wie folgt ist:

%Vor%

oder besser String # chr ,

%Vor%

Letzteres zeigt, warum chr nicht die beste Wahl für den Variablennamen ist.

Weiter

%Vor%

Ich werde nun die Rückgabewerte einrücken, um zu betonen, dass wir permutation ein zweites Mal aufrufen. Das Argument permuation lautet:

%Vor%

Wenn wir jetzt ausführen:

%Vor%

Wir geben ["b"] zurück, also (zurück zum ursprünglichen Aufruf von permutation ):

%Vor%

mit chr => "a" , früher berechnet. Nächstes:

%Vor%

Da perms nur das einzelne Element "b" enthält, vereinfachen sich die beiden for Schleifen zu:

%Vor%

was ist:

%Vor%

Beachten Sie, dass "b"[0..0] , "b"[0..1] und "b"[0..-1] alle gleich "b"[0] sind, was nur "b" und "b"[1..-1] #=> '' ist. Deshalb, wenn i => 0 , führen wir aus:

%Vor%

und wenn i => 1 :

%Vor%

so:

%Vor%

was eindeutig nicht das ist, was Sie wollen.

Was Sie tun müssen, ist, die doppelten for Schleifen zu ändern:

%Vor%

, das kompakter geschrieben werden könnte, indem die Methode String # eingefügt wird :

%Vor%

was normalerweise so geschrieben würde:

%Vor%

Beachten Sie, dass wir .dup die Zeichenfolge vor dem Senden von insert haben müssen, da insert die Zeichenfolge ändert.

Wenn Sie das so machen, brauchen Sie result = [] nicht. Sie benötigen auch nicht return result , da parms.each_with_object result zurückgibt und wenn keine return -Anweisung vorhanden ist, gibt die Methode die letzte berechnete Menge zurück. Außerdem benötigen Sie nicht die temporäre Variable perms (oder ch , falls gewünscht).

Wenn wir das zusammen machen, haben wir:

%Vor%

Versuchen wir es:

%Vor%

Eki, welcher bist du auf dem Bild?

    
Cary Swoveland 10.08.2014, 05:34
quelle
4

Sie können Array#permutation verwenden:

%Vor%

UPDATE Ohne usign Array#permutation :

%Vor%     
falsetru 10.08.2014 00:17
quelle

Tags und Links