6 Richtige Berechner optimieren



  • Hi,
    Ich wollt malwieder ein bisschen in die Vectorgeschichte reinkommen und habe daher ein kleines Progrämmchen gebaut:

    Es generiert solange 6 Zufallszahlen von 1 - 49 bis es 15 mal mit vorher eingegebenen 6 übereinstimmt.
    Sprich es berechnet wielange man mit den Zahlen brauchen würde bis man 6 richtige im Lotto hat.
    Das Programm scheint zu funktionieren, zumindest bekomme ich am Ende immer einen Durchschnitt so um die 14 Millionen raus, was rein rechnerisch richtig ist.
    Allerdings braucht das Programm fast 5 Minuten auf meinem 1,8 ghz Rechner und ich wollt mal zwecks Lerneffekt fragen wie ich das ganze beschleunigen kann. 😃

    #define WIE_OFT_GEWINNEN 15 // wie oft 6 richtige bekommen um zu beenden
    
    #include <conio>
    #include <vector>
    #include <iostream>
    #include <algorithm>  // Include algorithms
    
    using namespace std;
    
    int main(int argc, char* argv[])
    {
      randomize();
      vector<char> zahlen;
      zahlen.clear();
    
      // Die 6 Zahlen mit denen geraten wird
      zahlen.push_back(34);
      zahlen.push_back(2);
      zahlen.push_back(45);
      zahlen.push_back(12);
      zahlen.push_back(8);
      zahlen.push_back(27);
    
      sort(zahlen.begin(), zahlen.end());
      bool done = false;
      vector<char> ziehung;
      unsigned long versuche = 0;
      vector<long> versuche_puffer;
    
      for(char k = 0; k < WIE_OFT_GEWINNEN; k++)
      {
        done = false;
        while(!done)
        {
          ziehung.clear();
          for(char i = 0; i < 6; ++i)
          {
             ziehung.push_back(random(49)+1); // Zufallszahlen von 1 - 49
          }
          sort(ziehung.begin(), ziehung.end());
    
          bool doppelt = false;
          for(char i = 0; i < 5; ++i)
          {
            if(ziehung[i] == ziehung[i+1]) // eine Zahl ist doppelt vorhanden
            {
              doppelt = true;
              break;
            }
          }
    
          if(!doppelt)
          {
            bool gleich = 1;
            ++versuche;
            for(int i = 0; i < 6; ++i)
            {
              if(ziehung[i] != zahlen[i])
              {
                gleich = 0;
                break;
              }
            }
    
            if(gleich)
            {
              done = 1;
            }
          }
        }
        long alles_schnitt = 0;
        versuche_puffer.push_back(versuche);
    
        for(unsigned int i = 0; i < versuche_puffer.size();i++)
        {
          alles_schnitt += versuche_puffer[i];
        }
        alles_schnitt = alles_schnitt / versuche_puffer.size();
    
        cout << "Versuche: " << versuche << ", Schnitt: " << alles_schnitt << endl;
        versuche = 0;
      }
    
      getch();
      return 0;
    }
    


  • 1. Leg Dir ein bool-Array mit 49 Werten, wo du reinschreibst, welche random-Zahl schon gezogen wurde. Das erspart Dir die sowieso falsche Suche nach doppelten Werten.
    2. Leg Dir ein 2. bool-Array mit den zu testenden Werten an.
    3. Du kannst einen Vergleich auf Treffer sogar mit memcmp erledigen

    [ Dieser Beitrag wurde am 17.06.2003 um 12:27 Uhr von RenéG editiert. ]



  • gute Idee 😃
    aber mehr als 10% hat das auch nicht gebracht:

    #define WIE_OFT_GEWINNEN 15 // wie oft 6 richtige bekommen um zu beenden
    
    #include <conio>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    int main(int argc, char* argv[])
    {
      randomize();
      vector<char> zahlen;
      zahlen.clear();
    
      // Die 6 Zahlen mit denen geraten wird
      static bool vorgabe[50];
      vorgabe[34] = true;
      vorgabe[2] = true;
      vorgabe[45] = true;
      vorgabe[12] = true;
      vorgabe[8] = true;
      vorgabe[36] = true;
    
      bool done = false;
    
      bool ziehung[50];
      unsigned long versuche = 0;
      vector<long> versuche_puffer;
    
      for(char k = 0; k < WIE_OFT_GEWINNEN; ++k)
      {
        done = false;
        while(!done)
        {
          ++versuche;
    
          //for(int i = 0; i < sizeof(ziehung);++i)ziehung[i] = false;
          memset(ziehung,0,sizeof(ziehung));
    
          for(char i = 0; i < 6; ++i)
          {
             int zahl = random(49)+1;
             if(ziehung[zahl] == true)
             {
               --i; // zahl doppelt
             }
             else ziehung[zahl] = true;
          }
    
          if(memcmp(ziehung, vorgabe, sizeof(ziehung)) == 0)
          {
            done = true;
          }
        }
    
        long alles_schnitt = 0;
        versuche_puffer.push_back(versuche);
    
        for(unsigned int i = 0; i < versuche_puffer.size();++i)
        {
          alles_schnitt += versuche_puffer[i];
        }
        alles_schnitt = alles_schnitt / versuche_puffer.size();
    
        cout << "Versuche: " << versuche << ", Schnitt: " << alles_schnitt << endl;
        versuche = 0;
      }
    
      getch();
      return 0;
    }
    


  • Mit fast keiner Textausgabe und einem Durchschnitt von 12,6Mio und ein wenig Optimierung komme ich auf ca. 15 Sekunden auf einem Athlon 1,2GHz



  • na ok 10% war vieleicht etwas untertrieben der war nur beim ersten Durchlauf etwas hoch gelaufen, aber 3 Minuten braucht der bei mir wirklich für die 15 Versuche locker wenn er nicht grad verdammt viel Lottoglück hat.



  • Probier mal folgendes:

    #include <stdlib.h>
    #include <time.h>
    
    #define WIE_OFT_GEWINNEN 15 // wie oft 6 richtige bekommen um zu beenden
    
    typedef unsigned long ULONG;
    
    #define PROGRESS
    //#define LPROGRESS
    
    int main(int argc, char* argv[])
    {
      bool zahlen[49], ziehung[49];
      char cZiehung[6];
      ULONG versuche_puffer[WIE_OFT_GEWINNEN];
      // Die 6 Zahlen mit denen geraten wird
      memset( zahlen, 0, 49*sizeof(bool));
      memset( ziehung, 0, 49*sizeof(bool));
      memset( cZiehung, 0, 6*sizeof(char));
      zahlen[34] = zahlen[2] = zahlen[45] = zahlen[12] = zahlen[8] = zahlen[27] = true;
    
      randomize();
      for(ULONG k=1; k<=WIE_OFT_GEWINNEN; k++)
      {
        ULONG versuche = 0;
        while( true)
        {
          bool bFound = true;
          for( int i=0; i<6; i++)
          {
    loop:
            const char rd = (rand()*49)>>15; // Zufallszahlen von 0 - 48
        if( ziehung[rd] == true)
          goto loop;
        if( zahlen[rd] == false)
        {
          bFound = false;
          break;
        }
        ziehung[rd] = true;
        cZiehung[i] = rd;
          }
          // rücksetzen
          ziehung[cZiehung[0]] = ziehung[cZiehung[1]] = ziehung[cZiehung[2]] =
            ziehung[cZiehung[3]] = ziehung[cZiehung[4]] = ziehung[cZiehung[5]] = false;
          versuche++;
    #ifdef LPROGRESS
          if( (versuche%3000000) == 0)
        printf( "Versuche: %d\n", versuche);
    #endif
          if( bFound)
        break;
        }
        versuche_puffer[k-1] = versuche;
    #ifdef PROGRESS
        ULONG alles_schnitt = 0;
        for(ULONG i=0; i<k; i++)
          alles_schnitt += versuche_puffer[i];
        alles_schnitt /= k;
        printf( "Versuche: %d, Schnitt: %d\n", versuche, alles_schnitt);
    #endif
      }
      ULONG alles_schnitt = 0;
      for(ULONG i = 0; i < k; i++)
        alles_schnitt += versuche_puffer[i];
      alles_schnitt /= k;
      printf( "Schnitt: %d\n", alles_schnitt);
      return 0;
    }
    

    Musst halt bloss printf wieder durch cout ersetzen.



  • 😮 jo, rattert fleissig runter *beeindrucktsei*.
    Und was wars jetzt? das ich jedesmal memset auf die 64 gemacht hab? Sonst war da doch auch nimmer viel was Leistung kostet ausser dem rand auf das man ja nicht verzichten kann.



  • Und was wars jetzt?

    Zur richtigen Zeit ein break wirkt öfter Wunder als man denken mag!



  • noch schneller sollte es gehen, wenn man statt eines array die bit aus 2 32bit integer oder einen 64bit integer nutzt.


Anmelden zum Antworten