Lottozahlen ohne Wiederholung



  • @SeppJ sagte in Lottozahlen ohne Wiederholung:

    @It0101 sagte in Lottozahlen ohne Wiederholung:

    Weil das gezeigte "Original" ganz fürchterlicher Quellcode ist und mit C++ schonmal gar nichts zu tun hat? Vor 20 Jahren hat man das vielleicht so umgesetzt, aber in der heutigen Zeit ist das die Sorte Quellcode, die man nicht weiter verbreiten sollte.

    Vor 20 Jahren war Jahrtausendwende 😮
    Mach 60 Jahre draus, dann bist du ungefähr bei der Zeit wo solcher Code noch halbwegs akzeptabel war. "Go To Statement Considered Harmful" ist von 1968!

    Ich habe mit C bzw. C++ erst um die Jahrtausendwende angefangen, daher kann ich nicht bewerten was vorher war. Das "GOTO" mies ist, habe ich aber schon im Informatikunterricht anfang der 90er gelernt, weil das auch in Pascal ne blöde Idee war 😉



  • Hab ich ja wirklich 1995 geschrieben.
    Kann man aber sehr sehr sehr leicht umschreiben.
    Der Hacken ist eben, bei nur 6 aus 49 Zahlen kann man fast jedes System nutzen, um das
    ohne Wiederholung hinzukriegen. Wenn man aber per Transposition chiffrieren will und
    Zahlenreihen bis 13072 permutieren will, bleibt dir nur eine Kürzung eines bereits mit Zahlen
    befüllten Arrays übrig bei einer Permutierung einer Zahlenreihe wie die zuletzt genannte,
    kann das schon einige Minuten dauern. Mal abgesehen davon das die Zufallszahlengenerierung
    Systemabhängig ist. Bei Windows-Systemen liegt diese bei 0 bis 32767. Bei Linux-Systemen ist
    die Grenze bei etwa 200 000. Blöderweise kann man dabei keinen "Fortschrittsbalken" programmieren,
    da so lange die Z-Zahlen generiert werden, nichts am Terminal dargestellt werden kann.

    Aber die Sache mit dem Array und dem Kürzen wird zum Beispiel wichtig, wenn du Kartenspiele
    programmierst. Eine Karte die man ausgegeben hat, ist eben nicht mehr im Talon. Wenn du
    zum Beispiel Tarot nimmst, etwa Raider Wait Lenormand oder wie sie alle heißen, wie willst du sicher
    gehen, das eine Karte nicht mehr als einmal ausgegeben wird?

    Angeblich sollen ja auch gewisse amerikanische Geheimdienste die Finger drinn gehabt haben, als man
    festgelegt hat, auf welche Weise eine Zufallszahl generiert wird. Denn ab einer bestimmten Menge wird sich
    eine Wiederholung einstellen. Ist diese Spanne bisa zur Wiederholung zu groß, wetzen sich die Schlapphüte daran mal die Zähne ab.

    Übrigens gab es in Pascal das GOTO nicht. Der Programmrer sollte zu Objektorientierten Denken angeregt werden.
    Das Goto zu umgehen, sollte für jeden ein Kinderspiel sein.

    Ich war blos zu faul, das ganze vorher zu tun. Das überlasse ich den andern. Warum die Lösung gleich auf
    dem Silbertablett präsentieren?



  • @rustyoldguy
    Dein Code ist Schrott, einfach nur Schrott. Auch aus didaktischer Sicht.



  • Hab mal rum gekramt und eine "modernere Version gefunden":
    Zuerst genrand.h

    #ifndef GENRAND_H_INCLUDED
    #define GENRAND_H_INCLUDED
    
    #include  <iostream>
    #include  <time.h>
    
    
    void zeigezahlen(int zuzaar[], int zuzalimit);
    void initarreale(int obergrenze, int (*zuzaar)[66000], int (*schluessel)[66000], int (*wuerfel)[66000]);
    void kuerzearreal(int zuza, int og, int wuerfel[], int (*schluessel)[66000], int stelle);
    int getrand (int lowerlimit, int toprange);
    void testeareal(int og, int schluessel[]);
    
    #endif // GENRAND_H_INCLUDED
    

    Nun die dazugehörige genrand.cxx:

    #include "genrand.h"
    
    void zeigezahlen(int zuzaar[], int zuzalimit)
    {
    int zeize = 0, slei;
    std::cout << "\nZufallszahlen von 1 bis "<< zuzalimit << std::endl;
    
     for (slei = 0; slei < zuzalimit; slei++)
      {
      std::cout << "Nr." << slei << " = " << zuzaar[slei];
      zeize++;
      if (zeize >= 6) { std::cout << std::endl;; zeize = 0; }
      }
    }
    
    void initarreale(int obergrenze, int (*zuzaar)[66000], int (*schluessel)[66000], int (*wuerfel)[66000])
    {
    int slei;
     if (obergrenze > 65536) obergrenze = 65536;
    
     for (slei = 0; slei < 66000; slei++)
      {
       (*wuerfel)[slei] = 0;
       (*zuzaar)[slei] = 0;	
       (*schluessel)[slei] = 0; 	  
      }
    	  
     for (slei = 0; slei < obergrenze; slei++)
      (*wuerfel)[slei] = slei;
     
    }
    
    void kuerzearreal(int zuza, int og, int wuerfel[], int (*schluessel)[66000], int stelle)
    {
    int slei;
    
    (*schluessel)[stelle] = wuerfel[zuza];
    for (slei = zuza; slei < og; slei++)
     {
        wuerfel[slei] = wuerfel [slei + 1];
     }
     //std::cout << "\nog: " << og << "zuza: " << zuza << " stelle:" << stelle << "nach Kuerzung:   ";
     //for (slei = 0; slei < (og - 1); slei++)
     //std::cout << " -" << wuerfel[slei] << "- ";
    }
    int initrandom = 0;
    
    //generiert Zufallszahlen von 1 bis 65536
    int getrand(int min, int max)
    {
    int zuza, zuza2, zuza3, rewer;
    
     if (initrandom == 0)
      {
      srand (time (NULL));
      initrandom = 1;
      }
    
    zuza  = rand();
    zuza2 = (max - min); // + 1);
    zuza3 = zuza % zuza2;
    rewer = zuza3 + min;
    return rewer;
    }
    
    
    /* Errechnet die Summe aller Elemente des Zufallszahlenarreals */
    void testeareal(int og, int schluessel[])
    {
     int slei, dummy = 0, erge = 0;
    
    for (slei = 0; slei < og; slei++)
     {
      dummy += slei;
      erge += schluessel[slei];
     }
    std::cout << "\nAnzahl: "<< og << " Schlüssel: " << erge << "  Testwert: " << dummy << std::endl;
    if (erge != dummy)
     std::cout << "Fehler bei der Erstellung der Zufallszahlen" << std::endl;		
    }
    
    

    Jetzt main.cc:

    /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-  */
    /*
     * main.cc
     * Copyright (C) 2017 rustyoldguy
     * 
     * genzufallszahlen is free software: you can redistribute it and/or modify it
     * under the terms of the GNU General Public License as published by the
     * Free Software Foundation, either version 3 of the License, or
     * (at your option) any later version.
     * 
     * genzufallszahlen is distributed in the hope that it will be useful, but
     * WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     * See the GNU General Public License for more details.
     * 
     * You should have received a copy of the GNU General Public License along
     * with this program.  If not, see <http://www.gnu.org/licenses/>.
     *
     * Demonstrates how to generate a random| number between 1 and a given value.
     *
     * NOTE: In real use, you would not want| to call srand() before every call to
     * rand(), because if you call rand()| quickly in succession, it will keep
     * returning the same results. Instead,| move the call to srand to the beginning
     * of your program and only call it once. It works in this program, but only
     * because getrand() is called a single| time.
     */
    #include "genrand.h"
    
    
    int main (void)
    {
     int untergrenze, toprange = 49, slei, wohin = 8, dmog, sleia, zuza, anzahl = 6;
     int zuzaar[66000], schluessel[66000], wuerfel[66000];
     //int percent, vzaehler, vist;	
    
    untergrenze = 0;
    
    do
    switch(wohin)
    {
    default:
        std::cout << std::endl << "Zufallszahlengenerator" << std::endl;
        std::cout << "Obergrenze: " << toprange << std::endl;
        std::cout << "Ende...........................1" << std::endl;
        std::cout << "Obergrenze eingeben............2" << std::endl;
        std::cout << "Zahlen generieren..............3" << std::endl;
        std::cout << "Nur Zufallszahlen generieren...4" << std::endl;
        std::cout << "Anzahl der Zufallszahlen.......5" << std::endl;
        std::cout << "Ihre Wahl: ";
        std::cin >> wohin;
       break;
    
       case 1:
         std::cout <<  "Programmende" << std::endl;
         return 0;
        break;
    
    
    
       case 2:
         std::cout <<  "Obergrenze: (max 32768)";
         std::cin >> toprange;
         wohin = 8;
        break;
    
       case 3:
           std::cout << "Generiere Zahlen" << std::endl;
           if (toprange > 65536) toprange = 65536;
          initarreale(toprange, &zuzaar, &schluessel, &wuerfel);
    
          //zeigezahlen(zuzaar, toprange);
          //zeigezahlen(schluessel, toprange);
          //zeigezahlen(wuerfel, (toprange + 3));
          dmog = toprange;
          sleia = 0;
          // percent = toprange / 100;
    	  // vzaehler = vist = 0;	
    		
          for (slei = 0; slei < toprange; slei++)
           {
            zuzaar[slei] = getrand(untergrenze, dmog);
            kuerzearreal(zuzaar[slei], toprange, wuerfel, &schluessel, sleia);
            sleia++;
            dmog--;
            /*if (vzaehler++ > percent)
    		  {
               vist++;  
               std::cout << vist << "% ";
    		   vzaehler = 0;	
    		  }	
    		   */
    		if (dmog == 0 ) break;
           }
            
    	// Generierte Zufallszahlen zeigen
        // zeigezahlen(zuzaar, toprange);
        // zeigezahlen(schluessel, toprange);
        testeareal(toprange, schluessel);
    	std::cout << "Zahlen wurden generiert." << std::endl;
    		
    		
      wohin = 8;
     break;
    
     case 4:
         std::cout << "Nur " << anzahl << " Zufallszahlen generieren" << std::endl;
         for (slei = 0; slei < anzahl; slei++)
          {
          zuza = getrand (0, toprange);
           std::cout << " -" << zuza << "- " << std::endl;
          }
         std::cout << std::endl;
         wohin = 8;
        break;
    
    case 5:
        std::cout << "Bitte Anzahl der zu generierenden Zufallszahlen eingeben (maximal " << anzahl << ")" << std::endl;
        std::cin >> anzahl;
     break;
    
    }
    while(wohin != 0);
    
     return 0;
    }
    
    
    Was die Sache mit RAND_MAX angeht:
    ```cpp
    #include <iostream>
    #include <cstdlib>
    
    int main(void)
    {
     std::cout << "Wert von RAND_MAX: " << RAND_MAX << std::endl;
    	
     return 0;
    }
    


  • #Ausgabe bei mir:
    Wert von RAND_MAX: 2147483647



  • @Wutz sagte in Lottozahlen ohne Wiederholung:

    @rustyoldguy
    Dein Code ist Schrott, einfach nur Schrott. Auch aus didaktischer Sicht.

    /*
    "Anyone who consider arithmetic means of producing random number is,
    of course, in a state of sin" - John Von Neumann
    */

    In Wikipedia:
    https://de.wikipedia.org/wiki/John_von_Neumann

    Wer nicht weis was er mit seiner Freizeit unsinniges anfangen soll:
    https://www.subroutine.info/elektronik/zufallsgenerator/

    http://www.jtxp.org/tech/xr232web.htm

    http://www.hcrs.at/NOISE.HTM

    Heir was für( masochistisch veranlagte) Programmierer und Mathe-Freaks:
    https://123mathe.de/zufallsvariable-wahrscheinlichkeitsverteilungen-erwartungswert

    Meine Erfahrungen in der Stochastik:
    Ich habe mich immer gefragt was wohl trockener ist, die Wüste Gobi oder
    Kurvendiskussion, Stochastik, Wahrscheinlichkeitsverteilungen.
    Ich denke die Wüste Gobi ist weniger trocken!

    Zum Schluss:
    https://www.welt.de/wissenschaft/article1924410/Wie-kommt-der-Zufall-in-den-PC.html



  • @rustyoldguy sagte in Lottozahlen ohne Wiederholung:

    Übrigens gab es in Pascal das GOTO nicht

    Gab es übrigens doch.



  • @rustyoldguy sagte in Lottozahlen ohne Wiederholung:

    Hab mal rum gekramt und eine "modernere Version gefunden":

    da ist ja auch wieder eine globale variable drin.😃



  • @Wade1234 sagte in Lottozahlen ohne Wiederholung:

    da ist ja auch wieder eine globale variable drin.

    Das wär mir jetzt z.B. gar nicht erst aufgefallen, weil ich das auf den ersten Blick allein schon optisch so dermaßen hässlich finde, dass ich auf solche Details gar nicht mehr achte.
    @rustyoldguy nichts für ungut, nimmts nicht persönlich. Solchen Code will man zumindest in diesem Jahrtausend einfach nicht sehen.



  • @Jockelx sagte in Lottozahlen ohne Wiederholung:

    Hallo,

    typischer Algorithmus für Lottozahlen ziehen ist:

    
    Array a mit Zahlen 1 bis 49
    for i=0 bis 5
    {
      x = rand(49-i)
      result[i] = a[x];
      swap(a[x], a[49-i]); // gezogene Zahl aus dem rand-Bereich raus nehmen
    }