![]() |
AW: Erkennen von Zahlenpaaren
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
![]() Mein Lösungsansatz ist ausgehend von dieser Idee: Mal angenommen, es gäbe nur Kombinationen der Länge 2. Dann wäre es ja einfach: Man subtrahiert einfach alle Zahlen aus Menge1 von allen Zahlen aus Menge2. Dann muss man nur noch prüfen, welche dieser Differenzen auch tatsächlich in Menge1 liegen. Schon hat man alle gültigen Paare. Wenn man mehr als zwei Elemente pro Kombination zulässt, muss man den Ansatz etwas verallgemeinern: Man muss nun für jede Differenz schauen, ob sie wiederum durch eine Kombination von Elementen aus Menge1 gebildet werden kann. Das kann man wieder mit dem gleichen Algorithmus machen. So macht man es iterativ immer weiter, bis man am Ende Summen hat, die man mit einem einzelnen Element erfüllen kann. Der Trick ist, sich für jede Zwischensumme immer die kürzeste, bereits gefundene Kombination zu merken (Prinzip der ![]() Ich habe das mal als Proof-of-Concept implementiert. TCombinationTable sollte man in einer richtigen Implementierung als Hashtable implementieren, dazu war ich jetzt aber zu faul. Das Programm gibt allerdings immer nur die kürzeste Kombination aus, nicht, ob es noch weitere Kombinationen gibt. Das wäre IMO nur noch mit Brute-Force zu machen. Beispiel Ein- und Ausgabe:
Delphi-Quellcode:
PARTS: array [0..8] of Integer = (2,6,7,1,6,15,7,4,1);
SUMS: array [0..3] of Integer = (16,13,9,11);
Code:
16 = 15 + 1
13 = 7 + 6 9 = 7 + 2 11 = 7 + 4
Delphi-Quellcode:
PARTS: array [0..16] of Integer = (2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1);
SUMS: array [0..6] of Integer = (1,2,3,16,13,9,11);
Code:
Scheint zu funktionieren.
2 = 2
1 = 1 3 = 2 + 1 9 = 2 + 1 + 2 + 1 + 2 + 1 11 = 1 + 1 + 2 + 1 + 2 + 1 + 2 + 1 13 = 1 + 1 + 1 + 1 + 2 + 1 + 2 + 1 + 2 + 1 16 = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 2 + 1 + 2 + 1 + 2 + 1 Edit: Habe noch ein paar Fehler in meinem Code korrigiert, wegen denen die Laufzeit deutlich schlechter war als nötig. |
AW: Erkennen von Zahlenpaaren
Zitat:
Bau die Lösung schrittweise auf, und wirf nicht funktionierende Lösungen so schnell wie möglich weg. |
AW: Erkennen von Zahlenpaaren
Mh habe mal schnell was zusammengetippt (Ist in keinster Weise perfekt, aber funktioniert schnell und ohne Probleme).
Es geht in erster Linie ums Prinzip. Ist jetzt allerdings in C#:
Code:
Habe ich was nicht beachtet? Bin mir nicht sicher ob das immer die beste Lösung erzeugt, könnte es mir aber vorstellen.
class Program
{ private static int GetMaxFittingValueIndex(List<int> list, int DestValue) { int currIdx = 0; for (int i=list.Count-1; i >= 0; i--) { if (DestValue - list[i] == 0) return i; else if ((DestValue - list[i] > 0) && (list[i] > list[currIdx])) currIdx = i; } return currIdx; } static void Main(string[] args) { List<int> MengeA = new List<int>(new int[] { 2, 6, 7, 1, 6, 15, 7, 4, 1 }); List<int> MengeB = new List<int>(new int[] { 16, 13, 9, 11 }); Dictionary<int, List<int>> SummenMengeC = new Dictionary<int, List<int>>(); Console.Write("MengeA: "); for (int i = 0; i < MengeA.Count; i++) Console.Write(MengeA[i].ToString()+","); Console.WriteLine(); Console.Write("MengeB: "); for (int i = 0; i < MengeB.Count; i++) Console.Write(MengeB[i].ToString()+","); Console.WriteLine(); MengeA.Sort(); for (int i=0; i < MengeB.Count; i++) { List<int> currSummeList = new List<int>(); int currSumme = 0; while (currSumme < MengeB[i]) { int idx = GetMaxFittingValueIndex(MengeA, MengeB[i] - currSumme); currSumme += MengeA[idx]; currSummeList.Add(MengeA[idx]); MengeA.RemoveAt(idx); } SummenMengeC.Add(MengeB[i], currSummeList); } Console.WriteLine(); Console.WriteLine("Ergebnis:"); foreach(int zahl in SummenMengeC.Keys) { Console.Write(zahl.ToString() + " = "); for (int i=0; i < SummenMengeC[zahl].Count; i++) { if (i < SummenMengeC[zahl].Count - 1) Console.Write(SummenMengeC[zahl][i].ToString() + "+"); else Console.Write(SummenMengeC[zahl][i].ToString()); } Console.WriteLine(); } Console.ReadLine(); } } Irgendwelche Gedanken dazu? |
AW: Erkennen von Zahlenpaaren
Weiß nicht, ob ich deinen Code richtig verstehe, aber ich glaube, der findet nicht immer eine Lösung:
Probier mal
Code:
Ist aber eine gängige, schnelle Näherungslösung für das Rucksackproblem, soweit ich weiß.
List<int> MengeA = new List<int>(new int[] { 5, 5, 6, 15 });
List<int> MengeB = new List<int>(new int[] { 16 }); |
AW: Erkennen von Zahlenpaaren
Zitat:
Ich nehme mir nacheinander jede Zahl aus der 2. Menge und suche aus der ersten Menge die größten Zahlen mit denen ich die Summe bilden kann. 16: Größte Zahl <= 16 ist die 15 => 15 zur Summe hinzufügen und aus Menge1 entfernen, 1 ist übrig Größte Zahl <= 1 ist die 1 => 1 zur Summe hinzufügen und aus Menge1 entfernen, 0 ist übrig => fertig 13: Größte Zahl <= 13 ist die 7 => 7 zur Summe hinzufügen und aus Menge1 entfernen, 6 ist übrig Größte Zahl <= 6 ist die 6 => 6 zur Summe hinzufügen und aus Menge1 entfernen, 0 ist übrig => fertig usw. |
AW: Erkennen von Zahlenpaaren
Zitat:
Code:
Hier sind die Summen gleich, die Lösung für die 16 wird meines Erachtens aber trotzdem nicht gefunden.
List<int> MengeA = new List<int>(new int[] { 5, 5, 6, 15 });
List<int> MengeB = new List<int>(new int[] { 16, 5, 5, 5}); |
AW: Erkennen von Zahlenpaaren
Zitat:
Oder dürfen die Summen "mit zurücklegen" gebildet werden? Weil ansonsten fällt nach 16=5+5+6 der Rest so oder so flach. |
AW: Erkennen von Zahlenpaaren
Zitat:
Code:
Gut, da könnte man jetzt vielleicht sagen, MengeB muss auch absteigend sortiert sein. Habe ich jetzt zugegeben noch kein Gegenbeispiel für gefunden, aber es würde mich doch wundern, wenn es keines gäbe.
List<int> MengeA = new List<int>(new int[] { 5, 5, 5, 6, 15 });
List<int> MengeB = new List<int>(new int[] { 16, 20 }); |
AW: Erkennen von Zahlenpaaren
Zitat:
Wie gesagt: Ich hab selbst keinen Beweis dass das immer so funktioniert. Und wenn es "mit zurücklegen" ist, dann ist mein Code eh an der Aufgabenstellung vorbei :stupid: |
AW: Erkennen von Zahlenpaaren
Habe doch noch eins gefunden:
Code:
Oder auch
List<int> MengeA = new List<int>(new int[] { 13, 10, 4 });
List<int> MengeB = new List<int>(new int[] { 14, 13 });
Code:
Also ohne Backtracking wird es nicht gehen.
List<int> MengeA = new List<int>(new int[] { 13, 10, 4, 1 });
List<int> MengeB = new List<int>(new int[] { 14, 13, 1 }); |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:14 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz