dynamische Schleife - geht das?
-
Hallo,
ich habe in meinem Programm aktuell drei Schleifen
#include <iostream> using namespace std; int main() { int a, b, c, p; for (a=0; a<=100; a+=10){ for (b=0; b<=100; b+=10){ for (c=0; c<=100; c+=10){ p=a+b+c; if (p==100){ // mach was... } // Ende if } // Ende c } // Ende b } // Ende a return 0; }
Wenn ich jetzt noch eine vierte oder fünfte Variable hinzufügen möchte dann muss ich weitere Schleifen manuell einbauen. Ist es möglich sowas dynamisch zu machen? Also am Beginn die Anzahl der Schleifen festlegen und dann arbeitet das Programm genau so viele Schleifen durch.
/Andi
-
Ja! Es gibt verschiedene Moeglichkeiten, das zu erreichen. Aber es wird sehr selten gebraucht, da es bessere Wege gibt, das spezifische Problem zu loesen.
-
[hier stand Mist :P]
Willst du eine weitere Variable haben, mit der geloopt werden soll, musst du eine neue Schleife einbauen. Du kannst aber jederzeit schauen, was denn eigentlich genau passiert, wenn du die Schleifen ausschreibst, und entsprechend Code ohne Schleifen oder mit weniger Schleifen erstellen. Aber solange du nicht dein konkretes Problem schilderst, kann man dazu wenig sagen.
-
@knivil
Und was wären das für Wege?@l'abra d'or
Das verstehe ich jetzt nicht ganz. Wieso ist der Code sinnfrei und was wieso soll ich die Schleifen weglassen?
Ich möchte am Ende eine Liste mit Werten die in Summe 100 ergeben. BspA. B. C. 0 0 100 0 10 90 0 20 80 ... 0 100 0 10 0 90 10 10 80 ...
Diese Werte benötige ich um damit weiterzurechnen. Das funktioniert auch soweit. Jetzt ist es eben so dass es mal drei und mal mehr Variablen sind. Deswegen die Frage.
/Andi
-
also eine art bruteforce!?
kann man mittels rekursion lösen oder mit einem array.
wenn man nur werte umsortieren möchte, ist evtl. std::next_permutation das, was du gesucht hast...bb
-
Beispiel für 4 verschachtelte Schleifen, kann mühelos auf beliebig viele Schachtelungen erweitert werden.
#include <vector> #include <numeric> #include <algorithm> using namespace std; void mach_wat() { // Enthält den maximalen Index für jeden Zähler vector<unsigned int> MaxIndex( 4,0 ); MaxIndex[0] = 100; MaxIndex[1] = 100; MaxIndex[2] = 100; MaxIndex[3] = 100; // Enthält den aktuellen Index für jeden Zähler vector<unsigned int> CurrentIndex( 4,0 ); while( CurrentIndex[3] < MaxIndex[3] ) { // Summe aller Indizes bilden unsigned int p = accumulate( CurrentIndex.begin(), CurrentIndex.end(), 0 ); // Index erhöhen. Dazu wird der kleinste Index um 1 erhöht und geprüft, // ob dabei ein Überlauf auftritt. Wenn ein Überlauf auftritt werden alle // vorherigen Indizes auf 0 zurückgesetzt und der nächstgrößere Index um // 1 erhöht. Dabei muss wieder geprüft werde, ob bei diesem Index auch // ein Überlauf auftritt. unsigned int IncIndex = 0; while( IncIndex < 4 ) { if( ++CurrentIndex[IncIndex] == MaxIndex[IncIndex] ) { // Überlauf hat stattgefunden, Stellenindex erhöhen und alle // kleineren Indizes auf 0 zurücksetzen fill( CurrentIndex.begin(), CurrentIndex.begin() + (++IncIndex), 0 ); } else { break; } } } }
Edit:
Terminierungsbedingung korrigiert
-
wow, vielen Dank. Ich habe zwischenzeitlich eine Lösung für VBA gefunden, welche in Excel auch funktioniert. Diese wollte ich heute Abend dann mal in c++ umsetzten.
Wobei die Lösung von DocShoe deutlich kürzer ist! Werde mir beide Varianten zu Hause mal genauer anschauen. Nochmals vielen Dank!
Option Explicit Const n = 9 'Anzahl der Elemente (=Summanden) Const ziel = 100 'Zielsumme, die du mit n Summanden erreichen willst Const intervall = 10 '"Schachtelung" der Summanden Const min_Wert = 0 'fragwürdiges Zusatzfeature, entspricht aber deiner urspr. Anforderung: '0=>Lösungen dürfen für Elemente den Wert 0 beinhalten (sollte IMHO 1 sein) Const DUP = True 'false=nur eindeutige Mengenverteilungen, Position d. Elemente irrelevant '{E1=5, E2=10} == {E1=10, E2=5} => nur ein Eintrag bei (n=2, ziel=15, intervall=5) Dim zz, m 'lfd. Zeile für Ergebniseintrag Dim x() 'dyn. Array zum Speichern der einzelnen Lösung Dim zeit As Date Sub main() Sheets("Rekursion").Activate zeit = Now() 'Prüfen, ob die gewählten Parameter Lösungen zulassen... If ziel Mod intervall <> 0 Then MsgBox "Zielsumme nicht durch Intervall teilbar!", , "Abbruch" Exit Sub End If If n * intervall * min_Wert > ziel Then MsgBox "Zu viele Elemente oder zu grosses Intervall!", , "Abbruch" Exit Sub End If Cells.Clear 'Datenbereich leeren ReDim x(n - 1) 'Ergebnisarry dimensionieren Call neue_Kolonnen(True) 'erste Überschriften eintragen Call eb(1, 0) 'Rekursion starten MsgBox ("Lösungen insgesamt: " & 65355 * m + zz - 2 & " => " & zz & vbNewLine & Format(Now() - zeit, "HH:MM:SS ms")) End Sub Sub eb(ENr, ZwSumme) Dim Wert, bis_Wert If ENr = n Then x(ENr - 1) = ziel - ZwSumme If DUP = False And x(ENr - 1) < x(ENr - 2) Then Exit Sub Range(Cells(zz, 1 + n * m + m), Cells(zz, n + n * m + m)) = x zz = zz + 1 If zz = 65357 Then Call neue_Kolonnen(False) Else bis_Wert = (ziel - ZwSumme) / intervall For Wert = min_Wert To bis_Wert x(ENr - 1) = Wert * intervall If ENr > 1 And DUP = False Then If x(ENr - 1) >= x(ENr - 2) Then Call eb(ENr + 1, ZwSumme + Wert * intervall) Else Call eb(ENr + 1, ZwSumme + Wert * intervall) End If Next End If End Sub Sub neue_Kolonnen(ErstesMal As Boolean) Dim i As Integer zz = 2 If ErstesMal Then m = 0 Else m = m + 1 End If For i = 1 To n Cells(1, i + m * n + m) = "E" & i Next End Sub
-
sowosamma schrieb:
int main() { int a, b, c, p; for (a=0; a<=100; a+=10){ for (b=0; b<=100; b+=10){ for (c=0; c<=100; c+=10){ p=a+b+c; if (p==100){ // mach was... } // Ende if } // Ende c } // Ende b } // Ende a return 0; }
Das geht per Rekursion ganz schön. Auch kannst Du Dir viele unnütze Iterationen sparen, indem Du nicht bei jeder Schleife bis 100 gehen musst und die letztee Schleife eliminiert werden kann...
Skizze:
void ausgabe(int laenge, const int was[]); void dings(int laenge, int rest_summe, int speicher[], int position = 0) { if (position==laenge) { if (rest_summe==0) { // machwas ausgabe(laenge,speicher); } } else { ... } } int main() { const int laenge = 4; int s[laenge]; dings(laenge,100,s); }
Mehr verrat ich erstmal nicht.
-
dank Eurer Hilfe habe ich es glaube ich hinbekommen. Mein Code sieht jetzt so aus:
#include <iostream> using namespace std; int n = 4; int ziel = 100; int interval = 10; int anzahl = 0; //Funktionen void rekursion (int position, int rest_summe, int x[]) { int bisWert, wert; if (n == position) { x[position - 1] = ziel - rest_summe; anzahl++; for (int i=0; i<n; i++) { cout << x[i] << " "; } cout << endl; } // if TRUE else { bisWert = (ziel - rest_summe) / interval; for (wert=0; wert <=bisWert; wert++) { x[position-1] = wert * interval; rekursion(position+1, rest_summe + wert * interval, x); } // Ende wert } // if FALSE } // Funktionsende //Hauptprogramm int main() { int speicher[n]; rekursion(1, 0, speicher); cout << anzahl << endl; system("pause"); }
Das ist für 2 Wochen c++ Kenntnisse doch nicht schlecht? Vielen Dank nochmal!
/Andi