Permutationen

Kamikaze

Warrior of Sunlight
Teammitglied
Nach tagelangem Hickhack habe ich einen Algorithmus gefunden der Permutation mit der Effiziens O(n^2) erzeugt. Nach zahleichen Fehlschlägen ist mir die Wahrscheinlichkeitsrechnung wieder eingefallen, danach war die Lösung eigentlich offensichtlich.

Code:
/**
 * This class contains methods to create permutations of arrays.
 * 
 * @author		kamikaze
 * @version	1.00.2006.09.03
 */
public class Permutation {

	/**
	 * Allows calling the permutate() method from the command line.
	 * The first parameter is the number of the wanted permutation, all
	 * following parameters will be treated as array elements.
	 * 
	 * @param	args	The wanted permutation index and the array to
	 * 					create a permutation from.
	 */
	public static void main(String args[]) {
		long permutation = Long.parseLong(args[0]);
		String array[] = new String[args.length - 1];
		
		for (int i = 0; i < array.length; i++)
			array[i] = args[i + 1];
		
		permutate(array, permutation);
		
		for (int i = 0; i < array.length; i++)
			System.out.print(array[i] + " ");
		
		System.out.println();
	}
	
	/**
	 * Creates a permutation of an array. This method performs O(n^2).
	 * 
	 * @param	objects			An array to create a permutation from.
	 * @param	permutation		A number defining which permutation is wanted.
	 */
	public static void permutate(Object objects[], long permutation) {
		// A backup of the original array, required to build the new one.
		Object original[] = (Object[]) objects.clone();
		
		// Set all objects to null, to mark them as free.
		for (int i = 0; i < objects.length; i++)
			objects[i] = null;
		
		// Assign a new position to every object.
		for (int i = 0; i < objects.length; i++) {
			// Get the position for this object.
			int position = (int) (permutation % (objects.length - i));
			// Lower permutation for the next object.
			permutation /= objects.length - i;

			// Find the free position.
			int freePosition = 0;
			for (;position > 0 || objects[freePosition] != null; freePosition++)
				if (objects[freePosition] == null)
					position--;

			// Assign the position.
			objects[freePosition] = original[i];				
		}
	}
	
	/**
	 * Undoes the permutation of an array.
	 *  
	 * @param	objects			An array to turn into its original form.
	 * @param	permutation		A number defining which permutation the given
	 * 							array is.
	 */
	public static void unPermutate(Object objects[], long permutation) {
		// A backup of the given array, required for the reconstruction.
		Object permutated[] = (Object[]) objects.clone();
		
		// An array containing its index numbers.
		Integer order[] = new Integer[objects.length];
		for (int i = 0; i < objects.length; i++)
			order[i] = i;
		
		// Permutate the index numbers as the original objects are permutated.
		permutate(order, permutation);
		
		// Restore the original order.
		for (int i = 0; i < objects.length; i++)
			objects[i] = permutated[order[i]];	
	}
}

Der entsprechende Algorithmus ist in der Methode permutate implementiert. Das Progrämmchen kann auch mit dem gcj kompiliert werden.

--- edit ---
Habe permutateSlow() entfernt weil die Methode nicht funktioniert.
--- edit2 ---
Teilweise int mit long ersetzt.
--- edit3 ---
Optimierungen.
--- edit4 ---
Neue Methode unPermutate().
 
Zuletzt bearbeitet:
[LoN]Kamikaze schrieb:
Nach tagelangem Hickhack habe ich einen Algorithmus gefunden der Permutation mit der Effiziens O(n^2) erzeugt. Nach zahleichen Fehlschlägen ist mir die Wahrscheinlichkeitsrechnung wieder eingefallen, danach war die Lösung eigentlich offensichtlich.

Code:
/**
 * This class contains methods to create permutations of arrays.
 * Unfortunately the different algorithms don't yield the same results,
 * however they all create all possible permutations
 * within the range from 0 to n!.  
 * 
 * @author		kamikaze
 * @version	1.00.2006.09.03
 */
public class Permutation {

	/**
	 * Allows calling the permutate() method from the command line.
	 * The first parameter is the number of the wanted permutation, all
	 * following parameters will be treated as array elements.
	 * 
	 * @param	args	The wanted permutation index and the array to
	 * 					create a permutation from.
	 */
	public static void main(String args[]) {
		int permutation = Integer.parseInt(args[0]);
		String array[] = new String[args.length - 1];
		
		for (int i = 0; i < array.length; i++)
			array[i] = args[i + 1];
		
		permutate(array, permutation);
		
		for (int i = 0; i < array.length; i++)
			System.out.print(array[i] + " ");
		
		System.out.println();
	}
	
	/**
	 * Creates a permutation of an array. This method performs O(n!).
	 * 
	 * @param	objects			An array to create a permutation from.
	 * @param	permutation		A number defining which permutation is wanted.
	 */
	public static void permutateSlow(Object objects[], int permutation) {
		for (int i = 0; i < permutation; i++) {
			Object object = objects[i % objects.length];
			objects[i % objects.length] = objects[(i + 1) % objects.length];
			objects[(i + 1) % objects.length] = object;
		}
	}
	
	/**
	 * Creates a permutation of an array. This method performs O(n^2).
	 * 
	 * @param	objects			An array to create a permutation from.
	 * @param	permutation		A number defining which permutation is wanted.
	 */
	public static void permutate(Object objects[], int permutation) {
		// A backup of the original array, required to build the new one.
		Object original[] = (Object[]) objects.clone();
		// An array to remember which positions are already used.
		boolean taken[] = new boolean[objects.length];

		// Assign a new position to every object.
		for (int i = 0; i < objects.length; i++) {
			// Get the position for this object.
			int position = permutation % (objects.length - i);
			// Lower permutation for the next object.
			permutation /= objects.length - i;
			
			// Find the free positions.
			for (int p = 0; p < objects.length; p++)
				if (!taken[p]) {
					// If this is the wanted free position ...
					if (position == 0) {
						// ... use the position and mark it used.
						objects[p] = original[i];
						taken[p] = true;
						// End the loop.
						p = objects.length;
					}
					// Count down to the desired free position.
					position--;
				}
		}
	}
}

Der entsprechende Algorithmus ist in der Methode permutate implementiert. Das Progrämmchen kann auch mit dem gcj kompiliert werden.

Hi,

sehr schön sehr gut nur viel zu wuchtig :D halt typisch C verwandt :grumble:

Also es geht Dir primär um das sortieren ;) da hätte ich aber was viel kürzeres anzubieten: :cool:

Code:
PROCEDURESelectionSort(VARa:ARRAY[1..N]OFKeyType)=
VAR min:CARDINAL;
	t : KeyType;
BEGIN
FOR i :=1 TO N-1 DO
min	  :=i;
FOR j :=i+1 TO N DO
IF a[j] <a[min] THEN min :=j; END;
END;
t := a[min]; a[min] := a[i]; a[i] := t;
END;
END SelectionSort;

ja ja in der Kürze liegt die Würze, deshalb mag ich Modula so, genau die richtige Sprache für diese Aufgabe.

Allerdings haben C oder c lastige Sprachen (Java) dieses Problem viel zu komplex zu sein. (:

ps:
[seitenhiebmodus =an]


ja und das versteht auch jeder, wobei c oder c++ oder java ich mir da nicht so sicher bin !!
Naja vielleicht wenn man es von rechts nach links lesen tut :D

[seitenhiebmodus =aus]


mg > keinDummer
 
Zuletzt bearbeitet:
Was macht dein Algorithmus? Ich sehe nur einen Parameter (den Array). Wo gibt man an die wievielte Permutation man haben will?

So wie ich sehe hast du einen Sortieralgorithmus, keinen Permutationsalgorithmus.
 
Zuletzt bearbeitet:
[LoN]Kamikaze schrieb:
Was macht dein Algorithmus? Ich sehe nur einen Parameter (den Array). Wo gibt man an die wievielte Permutation man haben will?

So wie ich sehe hast du einen Sortieralgorithmus, keinen Permutationsalgorithmus.

Erst mal einen schönen guten Morgen,

dann für die Mitleser um was es hier eigentlich geht:

Das Sortieren von Datensatzen ist ein wichtiger Bestandteil von vielen Anwendungen.
Laut IBM werden in kommerziellen Rechenanlagen 25% der Rechenzeit für das Sortieren aufgewendet [Mehlhorn88]. Die Efzienzanspruche an die Algorithmen sind dementsprechend hoch. Als Einstieg grundlegende,sog.elementare Sortierverfahren.
Definition:Sortierproblem
Gegeben sei eine Folge a[1],...,a[N] von Datensatzen(Records)mit einer Schlüssel-
komponente a.key (i = 1,...,N) und eine Ordnung = auf der Menge aller Schlüssel.
Das Sortierproblem besteht darin,eine Permutation p der ursprunglichen Folge zu
bestimmen.


Elementare Sortierverfahren:

• SelectionSort(SortierendurchAuswahl)
• InsertionSort(SortierendurchEinfugen)
• BubbleSort
• BucketSort

Hohere Sortierverfahren:

• MergeSort
• QuickSort
• HeapSort

auf was ich nur hinweisen wollte, das Du eine Sortierung gleichwelcher Art in Modulla mir erheblich weniger Aufwand realisieren kannst als in anderen C lastigen Sprachen.

Nachfolgend noch der Klassiker BubbleSort:
Code:
PROCEDUREBubbleSort(VARa:ARRAY[1..N]OFKeyType)=
VAR t :  KeyType;
BEGIN
FOR i : = N TO1 BY-1 DO
     FOR j := 2 TO i DO
           IF a[j-1]>a[j] THEN
             t := a[j-1];
            a[j-1]:= a[j];
            a[j]:=t;
        END;
    END;
 END;
END BubbleSort;

Durch wiederholtes Vertauschen von unmittelbar benachbarten Schlüsselelementen, wandern die größeren Schlüssel nach und nach an das rechte Ende des zu sortierenden Feldes.Nach jedem Durchgang der aüßersten Schleife nimmt das großte Element der noch unsortiertenTeilfolge seine endgültige Position im Array ein.Dabei wird zwar im Verlauf der Sortierung auch der Ordnungsgrad aller noch unsortierten Schlusselelemente der Folge erhöht,jedoch ist BubbleSort nicht in der Lage,hieraus fur die weitere Sortierung einen Nutzen zu ziehen.

Ja das ist ein hochinteresantes Thema.

mg > keinDummer
 
Ich habe all diese Algorithmen schon implementiert, allerdings vergleichst du hier Bananen mit Schuhsolen. Ein Permutationsalgorithmus ist kein Sortieralgorithmus.

Ich sehe nichts an deinen Modulla Beispielen, das irgendwie einfacher als Java wäre. Im übrigen ist die Behauptung Java sei ähnlich zu C äquivalent zu der Behauptung Pascal sei ähnlich zu Assembler.
 
[LoN]Kamikaze schrieb:
Ich habe all diese Algorithmen schon implementiert, allerdings vergleichst du hier Bananen mit Schuhsolen. Ein Permutationsalgorithmus ist kein Sortieralgorithmus.
was aber nicht heissen soll, dass sortieralgorithmen nicht mit permutationen arbeiten :-)
wie ich gelesen habe, studierst du doch informatik(oder hast studiert), da solltest du in algorithmen & datenstrukturen(weiss nicht genau wie das bei euch in de heisst ;-)) in den ersten semestern, doch genug über sortierverfahren gelernt haben um das zu wissen..
 
[LoN]Kamikaze schrieb:
Ich habe all diese Algorithmen schon implementiert, allerdings vergleichst du hier Bananen mit Schuhsolen. Ein Permutationsalgorithmus ist kein Sortieralgorithmus.

Ich sehe nichts an deinen Modulla Beispielen, das irgendwie einfacher als Java wäre. Im übrigen ist die Behauptung Java sei ähnlich zu C äquivalent zu der Behauptung Pascal sei ähnlich zu Assembler.


nochmals guten morgen,

nun ja kommt darauf an welchen programmieransatz mann/frau verinnerlicht, da Du ja so vehemment für java eintreten tust ist bei Dir der rei objektorientierte Ansatz.

Obwohl da gibt es eigentlich nur 2 oder 3 Sprachen die das ohne Abstriche von sich behaupten können:

Smalltalk, Ruby und die 3. fällt mir jetzt gerade nicht ein


Modula-3 ist eine imperative, objektorientierte Programmiersprache. Sie versteht sich als Nachfolger von Pascal, Modula-2, Modula-2 plus und Cedar und wurde von DEC und Olivetti entwickelt. Sie wurde in der Tradition der Sprachen von Niklaus Wirth unter den Gesichtspunkten der Einfachheit und Strenge entwickelt, an der Entwicklung war Wirth allerdings nur als Berater beteiligt. Die Einfachheit bezieht sich hierbei auf den Sprachumfang (Die Sprachdefinition von Modula-3 umfasst 60 Seiten) und nicht auf die Länge der Programme oder auf eine Orientierung an persönlichen Programmiergewohnheiten.

Mein Ansatz ist ein etwas anderer wie Du meinen Beispielen entnehmen kannst, was Du allerdings nicht wegdiskutieren kannst ist die Tatsache das java und c miteinander verwandt sind.

Geschichte:

Die Urversion von Java – auch Oak genannt – wurde in einem Zeitraum von 18 Monaten vom Frühjahr 1991 bis Sommer 1992 unter dem Projektnamen The Green Project von Patrick Naughton, Mike Sheridan, James Gosling und Bill Joy sowie neun weiteren Entwicklern im Auftrag des US-amerikanischen Computerherstellers Sun Microsystems entwickelt. Einer der Urväter und Hauptentwickler der Sprache war dabei James Gosling. Überbleibsel aus dem Green-Projekt ist der Duke von Joe Palrang, der zum bekannten Symbol bzw. Maskottchen geworden ist.

Auszug Wikipedia

Die Programmiersprachen Java und C# haben eine ähnliche, ebenfalls an C angelehnte Syntax wie C++, sind auch objektorientiert und unterstützen Typparameter, weshalb ein Vergleich mit ihnen besonders naheliegend ist.

Aber darüber haben sich schon Generationen von Entwicklern gestritten und diesen Kampf brauchen wir nicht hier weiterzuführen.

mg > kein Dummer
 
Auch Deutsch und Polnisch haben eine ähnliche Syntax (Lateinisches Alphabet, .,-!?), trotzdem sind sie keine sonderlich ähnlichen Sprachen.

Meine eigentliche Frage lautet, was willst du mir mit deinen Modula Beispielen sagen? Warum zeigst du mir nicht einen O(n^2) oder sogar besseren Permutationsalgorithmus (von mir aus auch den gleichen) in Modula. Dann kann man direkt vergleichen welche Sprache weniger Aufwand erfordert.
 
[LoN]Kamikaze schrieb:
Auch Deutsch und Polnisch haben eine ähnliche Syntax (Lateinisches Alphabet, .,-!?), trotzdem sind sie keine sonderlich ähnlichen Sprachen.

Meine eigentliche Frage lautet, was willst du mir mit deinen Modula Beispielen sagen? Warum zeigst du mir nicht einen O(n^2) oder sogar besseren Permutationsalgorithmus (von mir aus auch den gleichen) in Modula. Dann kann man direkt vergleichen welche Sprache weniger Aufwand erfordert.

Aber hallo,

Du bist ja ein ganz Schlauer, wie wäre es denn mit Lernen sowie ich das auch musste ?? ;)

Habe Dir nur mal einen kleinen Denkanstoss gegeben, laufen musste schon selber :D

selbst auf die Gefahr hin das ich mich wiederhole, lesen bildet ungemein !!

http://www.vorlesungen.uos.de/informatik/java00/html/skript/1__1.htmld/index.html

mg > keinDummer
 
mann, was ist denn das fuer ein troll hier?

@keindummer: in modulo ist etwas weniger "aufwendig" ist keine besonders gute aussage. zumal dein "sortieralgorithmus" auch einer der ineffizienteren ist.
sag mir erstmal welcher von den von dir genannten immer eine laufzeit in theta(n log n) hat, dann darfst du weiter mit gift spritzen.

@kamikaze: danke fuer den permutationsalgorithmus!! ich glaube dass ich den die tage mal nach assembler hin uebersetzen werde.

p.s.: don't feed the troll!
 
Wow, den kann tatsächlich jemand gebrauchen. :)

Ich dachte mir den könnte ich vielleicht mal für Heuristiken verwenden.
 
dettus schrieb:
mann, was ist denn das fuer ein troll hier?
erst mal guten Tag,
also so wie Du mir unterstellst ein Troll zu sein, unterstelle ich Dir mal das Du von der C Fraktion herkommst.
Denn diese reagieren immer etwas gereizt auf Pascal/Oberon und Modula Programmierer.
dettus schrieb:
@keindummer: in modulo ist etwas weniger "aufwendig" ist keine besonders gute aussage. zumal dein "sortieralgorithmus" auch einer der ineffizienteren ist.
sag mir erstmal welcher von den von dir genannten immer eine laufzeit in theta(n log n) hat, dann darfst du weiter mit gift spritzen.
Wie sagte schon ein begnadeter Physiker geb. 14. März 1879 in Ulm gest.18. April 1955 in Princeton, USA alles ist ****** und vieles steht im Widerspruch.

mg > keinDummer
 
Glückwunsch zu diesem Post. Du hast es tatsächlich geschaft innerhalb weniger Zeilen deinen Gegenüber zu kategorisieren und in eine mit Voruteilenbelegte Schublade zu stecken. Klar hast du auch gemacht, dass du Modula-Fan bist, was in diesem Thema allerdings total uninteressant ist. Und zur Krönung willst du dich auch noch mit einem allesbedeutenden Zitat aus der Affäre ziehen. Mensch, du bist mir ja einer...

mfg
 
wie kann aus einem einfachen "ich hab was geschafft" fred so ein geflame entstehen?
programmiersprachen sind zum erschaffen von code da, nicht zum angeben, zicken, trollen, eingeschnappt sein und sonstwas.
wenn schon so wenige beiträge an einem sonntag morgen entstehen, dann doch bitte mit friede freude eierkuchen.

grüße,

jürgen (der vorhinnichtmalwusstewaseinepermutationist)
 
keinDummer schrieb:
Hi,

sehr schön sehr gut nur viel zu wuchtig :D halt typisch C verwandt :grumble:

Also es geht Dir primär um das sortieren ;) da hätte ich aber was viel kürzeres anzubieten: :cool:
ja ja in der Kürze liegt die Würze, deshalb mag ich Modula so, genau die richtige Sprache für diese Aufgabe.

Allerdings haben C oder c lastige Sprachen (Java) dieses Problem viel zu komplex zu sein. (:

[...]

ps:
[seitenhiebmodus =an]


ja und das versteht auch jeder, wobei c oder c++ oder java ich mir da nicht so sicher bin !!
Naja vielleicht wenn man es von rechts nach links lesen tut :D

[seitenhiebmodus =aus]


mg > keinDummer

Hi,
meinst du, für Goethes "Faust" wäre es von Bedeutung gewesen, ob er mit Bleistift oder Füller geschrieben wurde?
In der Regel ist die Wahl der Programmiersprache ähnlich unerheblich. Wichtig ist, wie man mit ihrer Hilfe ein Problem löst.

Gruss,
hirnzerfall
(Der diese lächerlichen Programmiersprachendiskussionen ziemlich satt ist)
 
Ich habe einen Permutationsalgorithmus der z.B. bei 12 Elementen im schlimmsten Fall 144 statt 479001600 Vertauschungen vornimmt. Dieser Thread soll meine Freude darüber zum Ausdruck bringen.

@keinDummer
Ich dachte zuerst du wolltest mir auf eine komplizierte Weise etwas mitteilen, aber anscheinend willst du blos eine Metadiskussion führen. Es steht dir frei ein neues Thema mit einem Aussagekräftigen Titel wie "Modulo ist am besten, aber ich verrate nicht warum." zu eröffnen. Bitte beschränke dich hier zukünftik auf Beiträge über Permutationsalgorithmen.

@Dettus
Danke für dein Interesse und dafür, das du hier mit Sachverstand in die Diskussion eingreifst. Es wäre schön wenn du deine Assemblerversion hier beisteuern würdest. Ich schreibe nämlich nur MIPS Assembler und würde gerne mal sehen wie das in x86 Assembler aussieht.
 
Wie ist denn die Methode permutateSlow zu verstehen?

Wenn ich mir den Methodeninhalt ansehe, würde ich doch mal von O(n) ausgehen, n ist in dem Fall die Permutation. Wie kommst du da auf O(n!)?

Und wie soll man die Methode verwenden? Wenn ich sie ganz stumpf mit dem permutate()-Aufruf in main austausche, so krieg ich völlig andere Ergebnisse. Vielleicht kannst du noch einen kommentierten Beispielblock einfügen, wie dieses O(n!)-Problem entsteht?
 
O(n!) bedeutet das im schlimmsten Fall n! Vertauschungen erfolgen. Das ist bei permutateSlow der Fall, da die Methode einfach iterativ von einer Permuation zur nächsten geht und es n! Permutationen gibt. Dabei ist n die Zahl der Elemente, nicht die gewünschte Permutation.

Wenn man die gewünschte Permutation in i ausdrückt, kann i Werte von 0 bis n! - 1 annehmen. Und es erfolgen immer i Vertauschungen.

Wie auch im Quelltext beschrieben erzeugen beide Algorithmen die Permutation nicht in der gleichen Reihenfolge. Trotzdem sind beides gültige Permutationsalgorithmen, da für beide gilt, dass für alle Zuordnungen i ==> f(i) im Intervall [0; n! - 1] die Zuordnungen bijektiv (eineindeutig) sind.
 
[LoN]Kamikaze schrieb:
Trotzdem sind beides gültige Permutationsalgorithmen, da für beide gilt, dass für alle Zuordnungen i ==> f(i) im Intervall [0; n! - 1] die Zuordnungen bijektiv (eineindeutig) sind.

Es werden aber nicht *alle* Permutationen gebildet, wenn ich das richtig sehe, zumindest nicht bei Deiner langsamen Variante.

Ich habe die mal gerade (in C) nachempfunden (siehe Attachment perms.c), wenn man da fuer alle Werte von 0..23 Dein permuteSlow() auf ein Array [0, 1, 2, 3] loslaesst, kommt jedes Ergebnis doppelt, dafuer fehlt aber die Haelfte (siehe perms.c.out).

Der Vollstaendigkeit halber habe ich noch eine Implementierung in Haskell angehaengt (perms.hs) inklusiver der davon erzeugten Ausgabe (perms.hs.out).

Oh, man kann hier keine Sourcen hochladen, wie ich gerade sehe, dann also direkt hier im Artikel:

perms.c:

Code:
#include <stdio.h>
#include <stdlib.h>

void perm(int *d, size_t s, int p) {
        int i;

        for (i = 0; i < p; i++) {
                int t = d[i % s];
                d[i % s] = d[(i + 1) % s];
                d[(i + 1) % s] = t;
        }
}

void testperm(int n) {
        int *d;
        int f, i, j;

        if(!(d = calloc(n, sizeof(int))))
                exit(EXIT_FAILURE);

        for (i = f = 1; i <= n; i++)
                f *= i;

        for (i = 0; i < f; i++) {
                for (j = 0; j < n; j++)
                        d[j] = j;
                perm(d, n, i);
                for (j = 0; j < n; j++)
                        printf("%d ", d[j]);
                puts("");
        }

}

int main(int argc, char *argv[]) {
        testperm(atoi(argv[1]));
        return 0;
}

Ausgabe dieses Programms mit Argument 4:

Code:
0 1 2 3 
1 0 2 3 
1 2 0 3 
1 2 3 0 
0 2 3 1 
2 0 3 1 
2 3 0 1 
2 3 1 0 
0 3 1 2 
3 0 1 2 
3 1 0 2 
3 1 2 0 
0 1 2 3 
1 0 2 3 
1 2 0 3 
1 2 3 0 
0 2 3 1 
2 0 3 1 
2 3 0 1 
2 3 1 0 
0 3 1 2 
3 0 1 2 
3 1 0 2 
3 1 2 0

Permutationsprogramm in Haskell:

Code:
module Main where

import List
import IO
import System

perms [] = [[]]
perms (x:xs) = concat $ map move (perms xs) where
        move xs = [ ys ++ (x : zs) | (ys, zs) <- zip (inits xs) (tails xs) ]

main = do
        [arg] <- getArgs
        n <- readIO arg :: IO Integer
        putStr $ unlines $ map unwords $ map (map show) $ perms[0 .. n - 1]

Und Ausgabe davon:
Code:
0 1 2 3
1 0 2 3
1 2 0 3
1 2 3 0
0 2 1 3
2 0 1 3
2 1 0 3
2 1 3 0
0 2 3 1
2 0 3 1
2 3 0 1
2 3 1 0
0 1 3 2
1 0 3 2
1 3 0 2
1 3 2 0
0 3 1 2
3 0 1 2
3 1 0 2
3 1 2 0
0 3 2 1
3 0 2 1
3 2 0 1
3 2 1 0
 
[LoN]Kamikaze schrieb:
O(n!) bedeutet das im schlimmsten Fall n! Vertauschungen erfolgen. Das ist bei permutateSlow der Fall, da die Methode einfach iterativ von einer Permuation zur nächsten geht und es n! Permutationen gibt. Dabei ist n die Zahl der Elemente, nicht die gewünschte Permutation.

OK, da hab ich mich versehen, n ist ja immer die Problemgröße, also die Anzahl der Elemente ... :)

[LoN]Kamikaze schrieb:
Wenn man die gewünschte Permutation in i ausdrückt, kann i Werte von 0 bis n! - 1 annehmen. Und es erfolgen immer i Vertauschungen.

Wie auch im Quelltext beschrieben erzeugen beide Algorithmen die Permutation nicht in der gleichen Reihenfolge. Trotzdem sind beides gültige Permutationsalgorithmen, da für beide gilt, dass für alle Zuordnungen i ==> f(i) im Intervall [0; n! - 1] die Zuordnungen bijektiv (eineindeutig) sind.

Angenommen, ich würde alle möglichen Permutationen haben wollen (also n!), dann wäre der "langsame" Algorithmus doch von Vorteil, da ich ja jederzeit den Array ausgeben kann, den überarbeiteten Array wieder reingebe und wieder einen Permutationsschritt weitergehe, bis so mit Aufwand von O(n!) alle n! Permutationen ausgegeben wurde (weniger geht ja nicht, wenn ich eh alle haben will).

Der O(n^2)-Algorithmus wiederum hat ja den Vorteil, dass ich schneller auf einen bestimmten Permutationsstand zurückgreifen kann, wobei (wie du schon sagtest), die Algorithmen unterschiedliche Permutationen bei der gleichen übergebenen Zahl liefern. Wenn ich es richtig verstanden habe, dann ist das insbesondere bei Verschlüsselungsverfahren von großem Vorteil.

Hat bei mir jetzt zwar bisschen lange gebraucht, zu verstehen worum es geht, aber dennoch: coole Lösung :cool:
 
@kili
Danke für den Hinweis, um ehrlich zu sein habe ich nur die Methode permutate() ausführlich getestet. Die Methode permutateSlow() ist anscheinend absoluter Schwachsinn. Deshalb habe ich sie einfach mal gelöscht.

Paldium schrieb:
Angenommen, ich würde alle möglichen Permutationen haben wollen (also n!), dann wäre der "langsame" Algorithmus doch von Vorteil, da ich ja jederzeit den Array ausgeben kann, den überarbeiteten Array wieder reingebe und wieder einen Permutationsschritt weitergehe, bis so mit Aufwand von O(n!) alle n! Permutationen ausgegeben wurde (weniger geht ja nicht, wenn ich eh alle haben will).
Wenn der langsame Algorithmus funktionieren würde, hättest du damit Recht (die Laufzeit wäre dann n!). Jedoch wächst n! so schnell, dass es nur bei sehr kleinen n Sinn macht alle Permutationen darzustellen. Und für kleine n ist es ja nicht so bedeutend das die Laufzeit mit dem schnellen Algorithmus für diese Aufgabe n!^3 ist.
 
Zuletzt bearbeitet:
Zurück
Oben