Rekursive Fkt. läuft nicht wie gewollt



  • Guten Tag

    hab angefangen mich in c++ einzulesen, hab also so gut wie keine erfahrung von daher entschuldige ich mich falls dies ein zu triviales Problem ist.

    Ich versuche in eine Datei Zeile für Zeile alle möglichen Folgen der Zahlen 0 und 1 der Länge n zu schreiben.

    Hab hier erstmal n=3 gesetzt:

    #include <iostream>
    #include <ostream>
    #include <fstream>
    
    using namespace std;
    
    int n=3;
    int t=1;
    int s=1;
    int *I = new int[n];
    int forfkt(int);
    
    int main()
    {
    	ifstream file("Indikatorfolge.txt");
    		if(file.is_open())
    		{
    		remove("Indikatorfolge.txt");
    		}
    
    	forfkt(t);
    }
    
    int forfkt(int t)
    {
    	std::ofstream ofs("Indikatorfolge.txt", std::ios::app);
    
    	for(I[t]=1; I[t]>=0; I[t]--)
    	{
    		if(t<n)
    		{
    			t++;
    		    forfkt(t);
    		}
    		else
    		{
    			for(s=1; s<=n; s++)
    			{
    		    ofs << I[s] ;
    			}
    			ofs << std::endl;
    		}
    
    	}
    
    };
    

    Als Ausgabe bekomme ich:
    111
    110
    101
    100

    Dies ist zwar schon schön, aber leider fehlen alle Kombinationen bei denen eine 0 vorne steht.

    Falls jemand eine simplere Methode hat wäre ich natürlich auch dafür dankbar,
    jedoch würde ich auch gern verstehen warum die Rekursion nur den Fall I[1]=1 durchläuft denn wenn ich es ohne Rekursion schreibe funktioniert es:

    #include <iostream>
    #include <ostream>
    #include <fstream>
    
    using namespace std;
    
    int n=3;
    //t=1;
    int *I = new int[n];
    
    int main()
    {
    	ifstream file("Indikatorfolge.txt");
    		if(file.is_open())
    		{
    		remove("Indikatorfolge.txt");
    		}
    
    	std::ofstream ofs("Indikatorfolge.txt", std::ios::app);
    
    	for(I[1]=1; I[1]>=0; I[1]--)
    	{
    
    		for(I[2]=1; I[2]>=0; I[2]--)
    		{
    
    			for(I[3]=1; I[3]>=0; I[3]--)
    			{
    				ofs << I[1] << I[2] << I[3] << std::endl;
    			}
    		}
    	}
    }
    

    Schonmal vielen Dank für die Hilfe.



  • also als einfachste methode bietet sich die stl an

    #include <algorithm>
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        int a[] = {1, 0, 0};
        for(int i = 0; i < 8; ++i)
        {
            next_permutation(a, a+2);
            cout << a[0] << a[1] << a[2] << endl;
        }
    }
    

    ungefähr so



  • Er will ja nicht permutieren, sondern {0,1}^3 aufzählen, wenn ich das richtig verstanden habe.



  • Du ändert t in Zeile 37. Das ist aber wohl nicht so gedacht. Es reicht t+1 der Funktion zu übergeben.

    Zudem ist dein Code ein Beispiel schlechten Stils 🙄



  • probiers mal damit, das hab ich vor ner ewigkeit im physik unterricht gemacht ( ich steh nicht auf physics 😃 )

    isn bissel allgemeiner

    übrigens, basiert darauf das ich ne formel für die eingänge der wahrheitstabellen gesucht hab, falls du den algorithmus nachvollziehen willst.

    #include <math.h>
    #include <iostream.h>
    //---------------------------------------------------------------------------
    // Lukas Bockel @ 27.5.08
    int main(int argc, char* argv[])
    {
      unsigned long Row;
      char Character [] = {  '0', '1' };
      /*
      char Character[26*2+10];
      for ( char i = 'a'; i <= 'z'; i ++ ){
        Character[i-97] = i;
      }
      for ( char i = 'A'; i <= 'Z'; i ++ ){
        Character[i-65+26] = i;
      }
      for ( char i = '0'; i <= '9'; i ++ ){
        Character[i+(2*26)-48] = i;
      }
      */
      //short AmoutofCharacters = 2*26+10;// Anzahl Buchstaben
      short AmoutofCharacters = 2;
      short StringLenght = 3;// Anzahl Character im zu erstellenden String
      /*
      cout << "Row Angeben.\n";
      cout << "Maximale Row = "<<pow(AmoutofCharacters,StringLenght)<<endl;
      cin >> Row;
      cout << endl;
      */
      char * String = new char[StringLenght];
      for ( int i = 0; i < StringLenght; i++)String[i] = 0;
      for ( Row = 1; Row <= powl(AmoutofCharacters,StringLenght); Row++){
        for ( int i = 0; i < StringLenght; i++ ){
          if ( Row > (powl(AmoutofCharacters,StringLenght)))break;// Falls ihr ohne die for schleife außen rum arbeitet das hier drinn lassen!
    
          unsigned long Calc =(((unsigned long)powl( AmoutofCharacters, i ))*AmoutofCharacters);
          unsigned long Temp = Row % Calc;
    
          if ( i == 0 ){//Ist es die erste Spalte?
            if ( Temp == 0 )Temp = AmoutofCharacters;
             String[i] = Character[Temp-1];
             //cout << Character[Temp-1];
          }else{
            if ( Temp == 0 ){// Wurde die Zahlenreihe schon Wiederholt?
              String[i] = Character [AmoutofCharacters-1];
              //cout << Character [AmoutofCharacters-1];
            }else {
              String[i] = Character [((int)ceil(Temp/powl( AmoutofCharacters, i )))-1];
              //cout << Character [((int)ceil(Temp/powl( AmoutofCharacters, i )))-1];
            }
          }
        }
      cout.write(String,StringLenght);
      cout << endl;
      }
      delete [] String;
    return 0;
    }
    //---------------------------------------------------------------------------
    


  • Wenn es auch iterativ sein darf, hätt ich für dich eine schnelle und kompakte Lösung.

    #include <iostream>
    #include <cmath>
    using namespace std;
    
    void printBin(const int n);
    
    int main()
    {
    	printBin(3);
    	return 0;
    }
    
    void printBin(const int n)
    {
    	int perm = pow(2, n);
    
    	for ( int i=0; i<perm; i++)
    	{
    		for ( int j=n-1; j>=0; j-- )
    		{
    			if ( i & ( 1 << j ) )
    				cout << 1;
    			else
    				cout << 0;
    		}
    		cout << endl;
    	}
    }
    

    Der Code führt zu folgender Ausgabe:

    000
    001
    010
    011
    100
    101
    110
    111

    Die Funktion funktioniert aber nur für: 1 <= n <= sizeof(int)*8



  • Vielen Dank an alle für die Hilfe, werde jetzt mal versuchen all die Alternativen zu verstehen.
    Die iterative Version gefällt mir wirklich gut. Und die Reichweite für n ist auch erstmal genug, aber woran liegt diese Beschränkung?

    @ lagalopex
    Ja ich gebe dir recht das mein code keinen Preis für Eleganz gewinnen würde, ich hab halt noch einiges an Büchern und Einführungen zu lesen. Hab erst vor ein paar Tagen damit angefangen und bin schon froh gewesen etwas zusammengebastelt zu bekommen was einigermassen das tut was ich wollte.
    Wäre natürlich für jeden Tip dankbar was man nicht machen sollte, damit ich mir garnicht erst was falsches angewöhne.



  • dfgbn schrieb:

    Vielen Dank an alle für die Hilfe, werde jetzt mal versuchen all die Alternativen zu verstehen.
    Die iterative Version gefällt mir wirklich gut. Und die Reichweite für n ist auch erstmal genug, aber woran liegt diese Beschränkung?

    Die Funktion gibt die Binärrepresentation einer int Zahl aus.
    also 1 mit z.B. 4 bit = 0001
    2 = 0010
    3 = 0011 usw.

    Folgender Teil

    if ( i & ( 1 << j ) )
    

    prüft sukzessive ob ein Bit an Stelle 0 bis n-1 gesetzt ist und gibt dementsprechend eine 1 oder 0 aus.
    Die Variable i wird also immer mit einem bitweisen UND und der Zahl 1 (geshiftet um j stellen nach links) verknüpft. Ist ein Bit an der zu vergleichenden Stelle gesetzt, ist das Ergebnis des bitweisen UND die Zweierpotenz dieser Stelle. Im anderen Fall ist das Ergebnis 0.

    Da ja nur die Binärrepresentation ausgegeben wird, funktioniert dies maximal für die Stellenanzahl eines int und die lässt sich mit sizeof(int)*8 bestimmen. Für noch breitere Bereiche könnte man die Schleifenvarible i z.B. als long long definieren und würde somit n auf sizeof(long long)*8 erweitern.


Anmelden zum Antworten