Hintergrund
Ich schreibe gerade an einem Programm für die Uni, welches 2 optimale Teams fürs Tauziehen erstellt.
Das Problem besteht aus einer Menge von Kindern mit verschiedenen Gewichten und eine Lösung gilt als optimal, wenn die Differenz der Gesamtgewichte der beiden Teams minimal ist.
Das schreibe ich jetzt nur fürs Verständnis, ob mein Algorithmus nur wirklich optimal oder effizient ist, ist hier nicht mein Anliegen (der angegebene Code ist auch nur ein Teil der Problemlösung) , mein eigentliches Problem ist folgendes:
Ich habe eine Funktion die folgendermaßen aussieht:
Problem
Dieser Code wirft eine
java.util.ConcurrentModificationException
Grund: während man über eine Collection iteriert, darf man sie anscheinend nicht verändern.
Jetzt habe ich mir folgendes überlegt:
Ich definiere zusätzlich die Variablen
Vector<Integer> neuesTeam1 = new Vector<Integer>();
Vector<Integer> neuesTeam2 = new Vector<Integer>();
neuesTeam1.addAll(team1);
neuesTeam2.addAll(team2);
und ersetze
durch
Dies wirft allerdings schon wieder neue Probleme auf.
Neue Probleme
Da ich nach Ausführung dieser Funktion die Listen team1 und team2 noch weiterbenutzen möchte, kann ich nicht einfach
team1 = neuesTeam1;
team2 = neuesTeam2;
machen, da ein Referenzenwechsel sich ja nicht auf den Paramter außerhalb den der Funktion auswirkt, oder?
Wenn ich allerdings
mache ist das denke ich mal
1. unelegant
2. langsam
Wir kriegen zwar unsere Punkte nach Korrektheit und nicht nach Performanz (solange es nicht länger als 5 Sekunden läuft) oder Eleganz, aber mich wurmt sowas schon.
Deshalb wäre ich sehr dankbar, wenn mir jemand eine bessere Lösung sagen könnte.
Mein weiteres Problem ist, dass, wenn ich die Kinder in den Teams drinlasse, ich beim weiteren Iterieren über
for(Integer kind1:team1)
for(Integer kind2:team2)
Ja dasselbe kind2 nochmal drannehmen könnte, was aber eigentlich schon entfernt ist.
Das einzige was mir jetzt einfällt ist, ein break einzusetzen, wenn ein kind getauscht wurde, dass würde allerdings meiner Meinung nach wieder die Performanz verlangsamen, weil man dieselben kinder, die schon anfangs nicht tauschbar waren beim Neudurchlauf der Schleife wieder erwischt.
Idee
Ein weiteres Problem ist für mich, dass ein break ja sicher nur aus der ersten For - Schleife springt und nicht aus der 2 und goto gibt es bei Java ja zum Glück nicht.
Wie könnte ich 1. aus den beiden for - Schleifen gleichzeitig springen oder 2. diese ganzen dummen Probleme gleich auf einmal erschlagen ohne so umständliche Workarounds zu veranstalten?
Wäre echt nett, wenn mir da ein erfahrener Listenjongleur helfen könnte, ähnliche Probleme mit Collections tauchen bei mir häufig auf.
Falls jemand Interesse an dem Problem hat und es selbst mal lösen möchte hier die Aufgabe. (bitte keine Lösungen zuschicken, den Algorithmus möcht ich schon selbst herausfinden
).
Ich schreibe gerade an einem Programm für die Uni, welches 2 optimale Teams fürs Tauziehen erstellt.
Das Problem besteht aus einer Menge von Kindern mit verschiedenen Gewichten und eine Lösung gilt als optimal, wenn die Differenz der Gesamtgewichte der beiden Teams minimal ist.
Das schreibe ich jetzt nur fürs Verständnis, ob mein Algorithmus nur wirklich optimal oder effizient ist, ist hier nicht mein Anliegen (der angegebene Code ist auch nur ein Teil der Problemlösung) , mein eigentliches Problem ist folgendes:
Ich habe eine Funktion die folgendermaßen aussieht:
Code:
public static int tauschen(Vector<Integer> kinder,Vector<Integer> team1,Vector<Integer> team2)
{
...
boolean verbesserung = true;
do
{
verbesserung = false;
for(Integer kind1:team1)
for(Integer kind2:team2)
// Tauschen dieser beiden Kinder würde eine Verbesserung bewirken?
if(Math.abs(sum1-sum2-2*kind1+2*kind2) < diff)
{
verbesserung = true;
team1.remove(kind1);
team2.remove(kind2);
team1.add(kind2);
team2.add(kind1);
sum1+=kind2-kind1;
sum2+=kind1-kind2;
diff = Math.abs(sum1-sum2);
}
}
while (verbesserung&&diff>0);
return diff;
}
Problem
Dieser Code wirft eine
java.util.ConcurrentModificationException
Grund: während man über eine Collection iteriert, darf man sie anscheinend nicht verändern.
Jetzt habe ich mir folgendes überlegt:
Ich definiere zusätzlich die Variablen
Vector<Integer> neuesTeam1 = new Vector<Integer>();
Vector<Integer> neuesTeam2 = new Vector<Integer>();
neuesTeam1.addAll(team1);
neuesTeam2.addAll(team2);
und ersetze
Code:
team1.remove(kind1);
team2.remove(kind2);
team1.add(kind2);
team2.add(kind1);
durch
Code:
neuesTeam1.remove(kind1);
neuesTeam2.remove(kind2);
neuesTeam1.add(kind2);
neuesTeam2.add(kind1);
Dies wirft allerdings schon wieder neue Probleme auf.
Neue Probleme
Da ich nach Ausführung dieser Funktion die Listen team1 und team2 noch weiterbenutzen möchte, kann ich nicht einfach
team1 = neuesTeam1;
team2 = neuesTeam2;
machen, da ein Referenzenwechsel sich ja nicht auf den Paramter außerhalb den der Funktion auswirkt, oder?
Wenn ich allerdings
Code:
team1.removeAllElements();
team2.removeAllElements();
team1.addAll(neuesTeam1);
team2.addAll(neuesTeam2);
1. unelegant
2. langsam
Wir kriegen zwar unsere Punkte nach Korrektheit und nicht nach Performanz (solange es nicht länger als 5 Sekunden läuft) oder Eleganz, aber mich wurmt sowas schon.
Deshalb wäre ich sehr dankbar, wenn mir jemand eine bessere Lösung sagen könnte.
Mein weiteres Problem ist, dass, wenn ich die Kinder in den Teams drinlasse, ich beim weiteren Iterieren über
for(Integer kind1:team1)
for(Integer kind2:team2)
Ja dasselbe kind2 nochmal drannehmen könnte, was aber eigentlich schon entfernt ist.
Das einzige was mir jetzt einfällt ist, ein break einzusetzen, wenn ein kind getauscht wurde, dass würde allerdings meiner Meinung nach wieder die Performanz verlangsamen, weil man dieselben kinder, die schon anfangs nicht tauschbar waren beim Neudurchlauf der Schleife wieder erwischt.
Idee
Code:
for(Integer kind1:team1)
for(Integer kind2:team2)
// Tauschen dieser beiden Kinder würde eine Verbesserung bewirken?
if(Math.abs(sum1-sum2-2*kind1+2*kind2) < diff)
{
verbesserung = true;
neuesTeam1.remove(kind1);
neuesTeam2.remove(kind2);
neuesTeam1.add(kind2);
neuesTeam2.add(kind1);
sum1+=kind2-kind1;
sum2+=kind1-kind2;
diff = Math.abs(sum1-sum2);
break;
}
}
Ein weiteres Problem ist für mich, dass ein break ja sicher nur aus der ersten For - Schleife springt und nicht aus der 2 und goto gibt es bei Java ja zum Glück nicht.
Wie könnte ich 1. aus den beiden for - Schleifen gleichzeitig springen oder 2. diese ganzen dummen Probleme gleich auf einmal erschlagen ohne so umständliche Workarounds zu veranstalten?
Wäre echt nett, wenn mir da ein erfahrener Listenjongleur helfen könnte, ähnliche Probleme mit Collections tauchen bei mir häufig auf.
Falls jemand Interesse an dem Problem hat und es selbst mal lösen möchte hier die Aufgabe. (bitte keine Lösungen zuschicken, den Algorithmus möcht ich schon selbst herausfinden