Zahlen per zufall abarbeiten



  • Du musst die Zahlen irgendwie in einen "Adressraum" abbilden, in dem du sie zufällig adressieren kannst.

    Pack die Zahlen in einen Vektor. Dann generiere Zufallszahlen im Bereich von 0 bis Anzahl_Zahlen-1 und arbeite den entsprechenden Eintrag im Vektor ab.

    Aus einem Vektor kannst du dann die Zahl entfernen und den Bereich der generierten Zahlen um 1 verringern.

    Damit deckst du die Annahme ab, daß jede Zahl, die im Vektor verbleibt, eine Wahrscheinlichkeit von 1/Anzahl_Zahlen hat, daß "ihre Zeit gekommen ist".



  • CStoll schrieb:

    Pack die alle der Reihe nach in einen Container (z.B. vector) und würfel sie dann einmal per random_shuffle() durcheinander.

    Und man lernt jeden Tag etwas Neues. DAS kannte ich noch nicht (s.o.) 😃



  • CStoll schrieb:

    Pack die alle der Reihe nach in einen Container (z.B. vector) und würfel sie dann einmal per random_shuffle() durcheinander.

    Da bekomme ich doch aber immer die gleiche "zufällige" Reihenfolge der Zahlen. Das sollte aber jedesmal eine andere Reihenfolge sein.
    Wie kann ich denn das dann noch reinbringen?



  • Niemand hindert dich daran, die Reihe neu durchzuwürfeln, wenn du fertig bist 😉


  • Mod

    evil-peter schrieb:

    CStoll schrieb:

    Pack die alle der Reihe nach in einen Container (z.B. vector) und würfel sie dann einmal per random_shuffle() durcheinander.

    Da bekomme ich doch aber immer die gleiche "zufällige" Reihenfolge der Zahlen. Das sollte aber jedesmal eine andere Reihenfolge sein.
    Wie kann ich denn das dann noch reinbringen?

    ich nehme an, random_shuffle basiert auf rand() - dann wäre es logisch, dass du den generator zuerst mit srand initialisieren solltest.



  • Mit srand() funktioniert das ertsmal ganz gut. Danke für den Tip.

    Ist aber doch ganz schön aufwendig oder vielleicht auch rechenintensiv, denn es sind knapp 600 Zahlen. Aber es sind halt immer die Zahlen von 1-600.
    Da gibt es doch bestimmt noch eine schnellere Lösung, Oder?


  • Mod

    eigentlich klingt diese methode recht effizient. ein random_shuffle führt jeweils n-1 swaps aus (insofern ist es wahrscheinlich sinnvoll, sie mehrmals anzuwenden, sonst bleibt ein signifikanter teil der elemente am platz). die idee von Sid macht zwar den eindruck, effizienter zu sein, aber das täuscht. letzlich hat sie eine O(n^2) komplexität - denn jedesmal, wenn ein element gelöscht wird, muss - im schnitt - der halbe vector umkopiert werden (oder bei eine list haben wir entsprechend viele iterationen, um zum gewünschten element zu kommen).



  • Jetzt habe ich noch ein Problem: das mit den Zahlen habe ich jetzt so gemacht und wollte das als Klasse definieren:

    #include "StdAfx.h"
    #include ".\random.h"
    
    void Random::zufall()
    {
    
    const int VECTOR_SIZE=21;
    IntVector Numbers(VECTOR_SIZE);
    
    for(int k=0; k<21;k++){ 
       Numbers[k] = k ;
    	}
    
       start = Numbers.begin();
    
       end = Numbers.end();
    
       srand( (unsigned)time( NULL ) );
       random_shuffle(start, end) ;
    	it=start;
    }
    

    und der Header:

    #pragma once
    #include <iostream>
    #include <algorithm>
    #include <functional>
    #include <vector>
    
    using namespace std ;
    
    class Random
    {
    public:
    
    	void zufall();
    
    private:
    
    typedef vector <int> IntVector;
    
    typedef IntVector::iterator IntVectorIt;
    
    IntVectorIt start;	
    IntVectorIt end;
    
    public:
    	IntVectorIt it;
    
    };
    

    Dann zufe ich das ganze im Dialog per Button auf:

    void CRandom_TestDlg::OnBnClickedButton1()
    {
    
    	Random test;
    	test.zufall();
    	CString in;
    		in.Format(_T("%d"),*test.it);
    		m_strAusgabe = in;
    		UpdateData (FALSE);
    }
    

    Nun gibt mir die Ausgabe aber nicht die gewünschte Zahl aus. Und außerdem würde ich gerne die Vectorgröße während der Laufzeit angeben wollen.
    Also Vectorgröße angeben?
    Wert des Vectors ausgeben?
    Was ist da falsch?

    Bitte um Hilfe



  • Hallo

    Also Vectorgröße angeben?

    Den User eine Zahl eingeben lassen und diese dann an deine Schleife zum Erzeugen der vector-Werte übergeben.

    Wert des Vectors ausgeben?

    EIn vector hat keinen Wert. Wenn du die einzelnen Elemente meinst, dann kannst du die alle in einer schleife nacheinander irgendwo ausgeben.

    bis bald
    akari



  • Das funktioniert einfach nicht.
    Sobald ich die Funktion verlasse sind die Werte in dem Vector nicht mehr vorhanden. Also beim ersten mal schon noch aber sobald ich die Werte weiter nutzen möchte, sind sie nicht mehr da.
    Das muß man doch irgendwie weiter speichern können!

    Wie soll das gehen, vielleicht mit Beispiel?



  • Hallo

    du erzeugst die Zufallszahlen in einem lokalen vector in der Funktion zufall(). Damit verfallen alle Werte sobald die Funktiopn beendet wird.
    Du kannst ganz einfach statt dem lokalen einen Member-vector nehmen

    #include "StdAfx.h"
    #include ".\random.h"
    
    void Random::zufall(int count)
    {
    
    Numbers.clear();
    for(int k=0; k<count;k++){
       Numbers.push_back(k);
        }
    
       start = Numbers.begin();
    
       end = Numbers.end();
    
       srand( (unsigned)time( NULL ) );
       random_shuffle(start, end) ;
        it=start;
    }
    
    #pragma once
    #include <iostream>
    #include <algorithm>
    #include <functional>
    #include <vector>
    
    using namespace std ;
    
    class Random
    {
    public:
    
      void zufall();
    
      typedef vector <int> IntVector;
    
      IntVector Numbers;
    
    };
    

    so hast du nach der Funktion zufall immer wieder Zugriff auf die erzeugten Zahlen, und auch noch eine variable Anzahl

    void CRandom_TestDlg::OnBnClickedButton1()
    {
    
        Random test;
        int Count = ...; // Hier Anzahl der zu erzeugenden Zahlen
        test.zufall(Count);
        test.Numbers ... // Hier Ergebnisse abrufen
        CString in;
            in.Format(_T("%d"),*test.it);
            m_strAusgabe = in;
            UpdateData (FALSE);
    }
    

    bis bald
    akari



  • Danke für die Antwort.
    Werde ich gleich mal probieren!!



  • Funktioniert leider auch nicht!

    Ich muß nochmal erklären, was ich machen will:

    Zahlenfolge von 0 bis n erzeugen. Diese Zahlen werden später als Index benötigt.
    Dann die Reichenfolge per Zufall ändern.
    Und dann die Zahlen nacheinander per Tastendruck abrufen und weiterverarbeiten.

    Ja und das habe ich noch immer nicht richtig hinbekommen!

    Kann mir nochmals jemand helfen?



  • Funktioniert leider auch nicht!

    Komische Fehlermeldung deines Compilers.
    🙄

    Was soll uns das sagen ?



  • Da kommt doch kein Compilerfehler!!!!!!!!!!!!!!! Habe ich irgendwas von Compilerfehler erzählt!

    Beim ausführen kommt einfach nicht der entsprechende Wert, sondern irgendwas mit "23423432423", also ein leerer Vector!!!


  • Mod

    evil-peter schrieb:

    Da kommt doch kein Compilerfehler!!!!!!!!!!!!!!! Habe ich irgendwas von Compilerfehler erzählt!

    nein

    evil-peter schrieb:

    Beim ausführen kommt einfach nicht der entsprechende Wert, sondern irgendwas mit "23423432423", also ein leerer Vector!!!

    das hast du uns auch nicht erzählt. zeig doch mal den exakten code, den du jetzt getestet hast. der von akari kann es ja nicht sein, denn dort ist noch ein fehler enthalten (der zu einem fehler beim compilieren führt).



  • Nein den habe ich so natürlich nicht übernommen! Ich habe das jetzt alles schon wieder umgeändert. Ich habe ja eine funktionierende Version, aber eben nicht als Klasse. Ich möchte das aber gerne als Klasse definieren, um das auch später leichter zu implementieren.

    Der Code ist ja im Prizip so, wie ich ihn schon mal gepostet hatte. weiter vorn!!



  • So jetzt habe ich das noch mal so gemacht: Hier der Code:

    die Klasse

    #pragma once 
    #include <iostream> 
    #include <algorithm> 
    #include <functional> 
    #include <vector> 
    
    using namespace std ; 
    
    class Random 
    { 
    public: 
    
      void zufall(int count); 
    
    typedef vector<int> IntVector ;
    
    typedef IntVector::iterator IntVectorIt;
    
    IntVector Numbers;
    
    IntVectorIt start;	
    IntVectorIt end;	
    IntVectorIt it;	
    
    };
    

    Der code:

    #include "StdAfx.h"
    #include ".\random.h"
    
    void Random::zufall(int count) 
    { 
    for(int k=0; k<count;k++){ 
       Numbers.push_back(k) ;
    	}
       start = Numbers.begin();
       end = Numbers.end();
    
       srand( (unsigned)time( NULL ) );
       random_shuffle(start, end) ;
       it=start;
    }
    

    Und der Aufruf in dem Dialog:

    void CRandom_TestDlg::OnBnClickedButton1()
    { 
    
        Random test;
        CString in; 
            in.Format(_T("%d"),*test.it); 
            m_strAusgabe = in; 
            UpdateData (FALSE); 
    }
    

    Und da passiert halt das, daß der Vector beim Buttonklick keine werte mehr hat. Da kommt dann aucch ein Absturtz.
    Mehr kann ich da jetzt auch nicht zu sagen



  • Das habe ich noch vergessen:

    Random test; 
        int Count = 10;
        test.zufall(Count);
    

    Bei Programmstart aufgerufen

    Ich habe das mir jetzt noch mal angesehen. Also sobald ich die Klasse Random im Dialog beim klicken wieder aufrufe wird natürlich der Vector wieder gelöscht. Die frage wäre jetzt wie ich den Vector komplett zurückgeben könnte?



  • Das ganze Problem ist wirklich, wie ich den vector nach dem abarbeiten der Funktion gespeichert bekomme. Das mit der Klasse funktioniert ja soweit jetzt.

    Muß ich da etwa einfach nur einen anderen Vector in dem Dialog definieren und dann mit dem aus der Klasse gleichsetzen?


Anmelden zum Antworten