Moin moin,
ich habe folgendes Problem, bzw. frage ich mich, ob es eine elegantere Variante gibt (wovon ich mal ausgehe 😉.
Ich habe zwei Werte z.B. X, Y von 0..n. Ich möchte jetzt beide Werte an eine Methode übergeben, dabei sollen aber keine "gleichen" Werte verglichen werden und zwar nicht 1 und 1, aber ebenso ist 1 und 0 gleichbedeutend mit 0 und 1.
Ich habe mir jetzt zur Hilfe ein Integerarray genommen, in dem ich mir die ersten Werte nehme z.B. prüfe ich X1, Y2 und trage in mein Array 12 und 21 ein.
Wenn dann die Prüfung auf X2, Y1 läuft, überspringe ich den Schritt.
Da muss es doch eine viel elegantere Lösung geben oder?
Vielen Dank im Voraus für eure Ideen
Stefan
p.s.: ich habe hier als Test für X und Y einen Wert genommen.
int Number = 4;
int[] used = new int[Number * Number];
int counter = 0;
int toCheck = 0;
for (int i = 0; i < Number; i++)
{
for (int j = 0; j < Number; j++)
{
if (i != j)
{
toCheck = int.Parse(i.ToString() + j.ToString());
if (!used.Contains(toCheck)) //combination does not exist?
{
Console.WriteLine("Adding:" + i.ToString() + j.ToString() +
"\nand :" + j.ToString() + i.ToString());
used[counter++] = int.Parse(i.ToString() + j.ToString());
used[counter++] = int.Parse(j.ToString() + i.ToString());
}
else
{
Console.WriteLine("DOUBLE:" + toCheck);
}
}
}
}
Hallo masterkrueger,
uff, ich habe den Text nun 3x lesen müssen, um eine Ahnung davon zu bekommen, was du vor hast.
Du willst alle Permutation von [0, 0] bis [n, n] berechnen und doppelte (bzw. die die in umgekerhter Reihenfolge schon einmal aufgetaucht sind) aussortieren?
Eine schöne Lösung fände ich, diese Paare [x,y] als Klasse zu kapseln und HashCode() so zu überschreiben, dass [x,y] und [y,x] den gleichen Hashwert liefern. Das würde ich so machen, dass ich diese sortiere (bspw. größere Zahl immer links) und danach eine bijektive Funktion von N² -> N (eigentlich reicht sogar eine injektive) konstruiere. Google sollte dir da helfen.
Weil es mich grad interessiert hat und ich nochmal kurz auffrischen wollte habe ich eine gesucht: hash = 2^(x-1)*(2y-1)
Im Anschluss einfach alle erzeugen und in ein HashSet packen.
Grüße
toCheck = int.Parse(i.ToString() + j.ToString());
ist auf alle Fälle nicht elegant 😉
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Soweit ich das sehe, sollte es reichen, wenn du nur das Paar nimmst, bei dem x kleiner ist als y (oder anderes herum).
Also z.B. folgendermaßen:
int Number = 4;
for (int i = 0; i < Number; i++)
for (int j = 0; j < Number; j++)
if (i!=j && i<j)
{
Console.WriteLine(i+";"+j);
}
Ergibt für dein Beispiel: 0;1 0;2 0;3 1;2 1;3 2;3
Hallo,
toCheck = int.Parse(i.ToString() + j.ToString());
ist nicht nur nicht elegant, es funktioniert auch nur, solange alle verglichenen Zahlen immer nur einstellig sind. Denn "123" könnte sowohl bei (1;23) als auch bei (12;3) entstehen.
Bei der Methode mit dem Hashwert müsste ebenfalls darauf geachtet werden, dass dieser Wert bei allen erdenklichen Kombinationen immer ein eindeutiges Ergebnis liefert.
Ich würde daher bei den ursprünglichen Zahlen bleiben, man könnte z.B. mit einem Dictionary<int,List<int>>
arbeiten, wo man dann den kleineren der verglichenen Werte als Key nimmt und in der Liste des Value alle bereits mit diesem Wert verglichenen Zahlen aufnimmt.
EDIT: Dann bei einem neuen Paar erst mal schauen, ob einer der beiden Werte bereits als Key im Dictionary steckt -> falls ja, dessen Liste durchlaufen und wenn der andere Wert nicht gefunden wird, diesen dort eintragen.
Gruß, MarsStein
@dN!3L: Geht aber nur, wenn alle Paare auch doppelt in vertauschter Form vorkommen.
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca
Bei der Methode mit dem Hashwert müsste ebenfalls darauf geachtet werden, dass dieser Wert bei allen erdenklichen Kombinationen immer ein eindeutiges Ergebnis liefert.
Deshalb meinte ich ja eine injektive Funktion. Ich habe mal eine reineditiert.
@dN!3L: Geht aber nur, wenn alle Paare auch doppelt in vertauschter Form vorkommen.
Wie es im von masterkrueger geposteten Beispiel ja der Fall ist.
Wow, vielen Dank für die ganzen Antworten, ich werde meine Funktion wohl erstmal an die von dN!3L angleichen, das trifft genau mein Beispiel, obwohl ich das Dictionary auch gut finde.
Aber indem gleich geprüft wird, dass keine größeren Werte verglichen werden, macht die Sache ja schonmal um einiges schlanker.
Danke!!!
Stefan
Mal eine frage zu der Funktion von dN!3L
Wäre es nicht deutlich besser
int Number = 4;
for(int a = 0; a < Number; a++)
for(int b = a +1 ; b < Number; b++)
Console.WriteLine("{0};{1}",a,b);
Ja, aber nur solange der Wertbereich gleich bzw. in b größer als in a ist.
q.e.d.
Bezogen auf den Eingangsbeitrag ist aber die Lösung von PPK eindeutig die beste.
Und bei der Lösung von dN!3L sollte man die Abfrage noch zu
if (i<j)
verkürzen (denn wenn i<j, dann ist ja automatisch i!=j).
Wenn man jedoch zwei Listen von Zahlen hätte und anhand der Inhalte (anstatt der Indizes) vergleichen möchte, dann kommt man um die Abfrage nicht herum.
Obwohl es hier für eine Lösung fors (und teilweise ifs) braucht, bewegt sich die Aufgabenstellung noch klar im Bereich von [Hinweis] Wie poste ich richtig? Punkt 1.1.1.