Array Wörter Zufällig aufrufen



  • Belli schrieb:

    Ansonsten hat ja wob bereits eine Variante vorgeschlagen.

    Die aber nebenbei auch kein guter Rat ist - sehe ich jetzt erst.
    std::random_device als Default "nimm mal einfach den" Generator zu empfehlen ist IMO ganz schlechter Rat. std::random_device kann nämlich schön teuer werden. Beliebig teuer. Und garantiert gleichzeitig nix was die Qualität der Zahlen angeht.



  • hustbaer schrieb:

    Belli schrieb:

    Ansonsten hat ja wob bereits eine Variante vorgeschlagen.

    Die aber nebenbei auch kein guter Rat ist - sehe ich jetzt erst.
    std::random_device als Default "nimm mal einfach den" Generator zu empfehlen ist IMO ganz schlechter Rat. std::random_device kann nämlich schön teuer werden. Beliebig teuer. Und garantiert gleichzeitig nix was die Qualität der Zahlen angeht.

    Gut, ich dachte, dass es für 25 Zahlen ggf. nicht lohnt, da einen std::mt19937 zu nutzen. Den ich dann einfach auch aus random_device seede - und zwar meistens mit einer einzigen Zufallszahl, obwohl der Zustand des mt19937 größer ist. Und ne seed_seq... naja, mir ist unklar, wie viel Werte ich auch dem random_device reintun müsste, damit der mt vollständig zufällig initialisiert wird. Eigentlich schade, dass man nicht das random_device direkt an den mt-Constructor übergeben kann.

    Und für die Garantien: die macht der C++-Standard zwar nicht, aber z.B. nutzt libc++ meines Wissens einfach /dev/urandom.

    Aber generell hast du schon recht: sobald man ein paar mehr Zahlen braucht, sollte man schon wissen, welchen Generator man gerade nutzt und wie lange er für die Berechnung einer Zufallszahl braucht.

    In der überwiegenden Anzahl Fälle wird folgendes das beste/einfachste sein:

    // einmalig den rng initialisieren, meistens recht eine Zufallszahl aus.
    std::mt19937 rng(std::random_device{}());
    
    // ab jetzt nur noch rng benutzen, z.B.
    std::cout << std::uniform_int_distribution<int>(0, 100)(rng) << '\n';
    std::cout << std::normal_distribution<double>(10.0,1.0)(rng) << '\n';
    


  • Danke erstmal für die Hilfe!

    Mittlerweile funktioniert es so wie ich es mir vorgestellt habe. Allerdings ist mir nun ein weiteres Problem in den Sinn gekommen was ich vorher nicht bedacht habe.

    Die Wörter können doppelt vorkommen, was sehr ungünstig ist. Ich habe gedacht das mit einer if-Bedingung zu lösen allerdings komm ich nicht darauf wie ich das denn vergleichen sollte.

    Hab schon einiges versucht was ich über doppelte Zufallszahlen gefunden habe, aber irgendwie hat es mich einfach nicht weiter gebracht.

    Hat hier nochmal jemand einen Tipp?



  • Jo...
    Wenn du keine Duplikate willst musst du dir iwie merken, welche Zahl(en) du bereits gezogen hast und musst die dann ignorieren. Da deine Tiernamen etwas ungünstig organisiert sind schlage ich folgende Lösung vor:

    1. Zu Beginn hast du 75 Tiernamen mit den Indizes 0-74
    2. Du füllst eine Liste (std::vector) mit allen gültigen Indizes
    3. Du wählst zufällig einen Eintrag aus dieser Liste aus und gibst den Tiernamen an diesem Index aus.
    4. Du löschst den Eintrag aus der Liste
    5. falls <25 Tiernamen ausgegeben weiter bei 3
    6. fertig


  • Hallo hustbaer,

    hustbaer schrieb:

    ... denn es gibt besseres als MT (Mersenne Twister), z.B. Xorshift/Xoroshiro

    Interessant! wieder ein neuer RNG - den kannte ich noch nicht. Ich benutze seit einiger Zeit pcg32, und bei meinen Anwendungen werde ich wahrscheinlich zwischen MT, pcg32 oder Xoroshiro128+ keinen Unterschied feststellen.
    pcg32, und auch Xoroshiro128+ wie ich sehe, hat gegenüber MT den Vorteil wesentlich weniger Resourcen zu verbraten.

    Gruß Werner



  • DocShoe schrieb:

    1. Du füllst eine Liste (std::vector) mit allen gültigen Indizes

    Ich hab allerdings noch nicht damit gearbeitet, kann also gerade noch recht wenig damit anfangen. Und bin mir auch nicht wirklich darüber bewusst wie ich das anwenden muss.



  • moglie23 schrieb:

    Ich hab allerdings noch nicht damit gearbeitet, kann also gerade noch recht wenig damit anfangen.

    Dann ist jetzt ein guter Zeitpunkt.

    moglie23 schrieb:

    Und bin mir auch nicht wirklich darüber bewusst wie ich das anwenden muss.

    Du möchtest 25 aus 75 haben.

    Beispiel für 3 aus 10:

    Liste = {0, 1, 2, 3 ,4 ,5 ,6 ,7 ,8, 9}
    Zufallszahl = 3, Liste[3] ist 3, gib Tier[3] aus
    lösche Element 3 aus Liste
    Liste = {0, 1, 2, 4 ,5 ,6 ,7 ,8, 9} // jetzt nur noch 9 Elemente
    Zufallszahl = 5, Liste[5] ist 6, gib Tier[6] aus
    lösche Element 5 aus Liste
    Liste = {0, 1, 2, 4 ,5 ,7 ,8, 9} // jetzt nur noch 8 Elemente
    Zufallszahl = 5, Liste[5] ist 7, gib Tier[7] aus
    lösche Element 5 aus Liste
    Liste = {0, 1, 2, 4 ,5 ,8, 9} // jetzt nur noch 7 Elemente
    


  • moglie23 schrieb:

    DocShoe schrieb:

    1. Du füllst eine Liste (std::vector) mit allen gültigen Indizes

    Ich hab allerdings noch nicht damit gearbeitet, kann also gerade noch recht wenig damit anfangen. Und bin mir auch nicht wirklich darüber bewusst wie ich das anwenden muss.

    Schau dir bitte mal dringend die STL an.

    Insbesondere solltest du kennen:
    http://www.cplusplus.com/reference/vector/vector/
    http://www.cplusplus.com/reference/string/

    Außerdem schau dir an, was es schon an fertigen Algorithmen gibt:
    http://www.cplusplus.com/reference/algorithm/

    Um einen std::vector mit Indizes (=aufeinanderfolgenden Zahlen) zu füllen, schau dir std::iota an (das suche ich immer in <algorithm> , es findet sich aber im Header <numeric> ).

    Da du ja zufällige Indizes haben willst, brauchst du nicht kompliziert aus der Mitte des Arrays herauszulöschen, sondern kannst stattdessen das letzte Element an diese Stelle kopieren und danach das letzte Element löschen. Das geht schneller.

    Wenn du nur "wenige Werte aus vielen" haben willst (und die die Reihenfolge egal ist), kannst du alternativ folgendes tun (Pseudcode für 6 aus 49):

    std::set<int> ergebnis;
    while (ergenis.size() < 6) {
      ergebnis.insert(get_random_value(1, 49));
    }
    

    Sowas ist gut, solange du nur wenige Werte ermitteln wirst, d.h. wenn du einen Wert doppelt ziehst, ziehst du einfach noch einmal. Das ist aber nicht sinnvoll, wenn du viele Dinge ziehen willst.



  • In der STL gibt es auch random_shuffle/shuffle.



  • Th69 schrieb:

    In der STL gibt es auch random_shuffle/shuffle.

    Oh ja, gute Idee 👍


Anmelden zum Antworten