de.grimmer: Eine Reihe von Zufallszahlen ohne Redundanz

Hallo liebe Poster und Helfer,

Ich möchte ein Array mit 60 Elementen mit
60 Zufallszahlen zwischen 0 und 59 , ohne redundante
Werte erzeugen.
Kann man mir helfen ??

d.grimmer

  1. Hi,

    Ich möchte ein Array mit 60 Elementen mit
    60 Zufallszahlen zwischen 0 und 59 , ohne redundante
    Werte erzeugen.

    sprich: Du möchtest ein Array, dessen Elemente ihren jeweiligen Index beinhalten, zufällig sortieren.

    Kann man mir helfen ??

    Hilft Dir diese andere Betrachtungsweise? :-) Wenn nicht: Denk Dir einfach zwei Arrays. Das eine ist zu Beginn sortiert gefüllt, das andere ist leer. Jetzt holst Du aus dem sortierten nacheinander zufällige Elemente raus, die Du dem anderen Array hinzufügst, bis das erste leer ist.

    Cheatah

    1. Hi,

      Ich möchte ein Array mit 60 Elementen mit
      60 Zufallszahlen zwischen 0 und 59 , ohne redundante
      Werte erzeugen.

      sprich: Du möchtest ein Array, dessen Elemente ihren jeweiligen

      Index beinhalten, zufällig sortieren.

      Kann man mir helfen ??

      Hilft Dir diese andere Betrachtungsweise? :-) Wenn nicht:

      Denk Dir einfach zwei Arrays. Das eine ist zu Beginn sortiert
      gefüllt, das andere ist leer. Jetzt holst Du aus dem sortierten
      nacheinander zufällige Elemente raus, die Du dem anderen Array
      hinzufügst, bis das erste leer ist.

      Cheatah

      An dem Punkt stehe ich auch gerade.
      Leider Funktioniert das Löschen eines zufällig ausgewählten Elementes
      meines Wissens nach nur, solange es das Erste oder Letzte ist !?
      Es gibt kein "Delete".
      Einzig "slice" käme als Methode in Frage?? aber der Rückgabewert ist
      eben das eine Element !?

      1. Hi,

        Einzig "slice" käme als Methode in Frage?? aber der Rückgabewert ist
        eben das eine Element !?

        na, freu Dich. Genau das willst Du doch haben.

        Cheatah

  2. Hallo liebe Poster und Helfer,

    Ich möchte ein Array mit 60 Elementen mit
    60 Zufallszahlen zwischen 0 und 59 , ohne redundante
    Werte erzeugen.
    Kann man mir helfen ??

    d.grimmer

    Hi d(e).grimmer

    naja, Zufall ist halt Zufall. Wenn ein Zufallswert von gewissen Vorbedingungen abhängig ist, ist es kein wirklicher Zufallswert mehr. Dein 60. (= letzter) Wert hat dann z. B. überhaupt nichts mehr mit Zufall zu tun. Tipp: Zufallswert plus Nachbearbeitung. Zufallswert ermitteln und nachsehen, ob diese Zahl schon gezogen wurde. Falls ja: verwerfen, falls nein: nehmen. Nicht die eleganteste oder gar laufzeitoptimierte Methode, aber einfach in der Implementierung.

    Ciao
    Hans-Peter

    1. Hi,

      naja, Zufall ist halt Zufall. [...] Zufallswert ermitteln und nachsehen, ob diese Zahl schon gezogen wurde. Falls ja: verwerfen, falls nein: nehmen.

      dieser Algorithmus ist nicht terministisch. Was ist, wenn der letzte noch fehlende Wert per Zufall (denn genau das ist es) nie gezogen wird?

      Cheatah

      1. Auch hi,

        dieser Algorithmus ist nicht terministisch. Was ist, wenn der letzte noch fehlende Wert per Zufall (denn genau das ist es) nie gezogen wird?

        na ja wie gesagt: Der Algorithmus ist nicht laufzeitoptimiert :-) Aber der letzte Wert _wird_ gezogen. Immerhin unterliegt der letzte Wert genau der gleichen Wahrscheinlichkeit wie alle anderen Werte. Es kommt halt drauf an, ob da ein Client / ein Besucher auf das Ergebnis warten muß, oder ob es wirklich völlig egal ist, wie lange die Berechnung dauert. Meine Lösung ist nicht genial, sie ist trivial (bestenfalls genial einfach).

        Hans-Peter

        1. Hi,

          na ja wie gesagt: Der Algorithmus ist nicht laufzeitoptimiert :-)

          stimmt :-)

          Aber der letzte Wert _wird_ gezogen. Immerhin unterliegt der letzte Wert genau der gleichen Wahrscheinlichkeit wie alle anderen Werte.

          Ja: 1/60. Die Wahrscheinlichkeit, bei n Ziehungen diesen Wert zu erhalten, beträgt _nicht_ n*1/60. Die Formel habe ich leider nicht mehr im Kopf (1-(1-1/60)^n?); aber nach n Versuchen ist die Wahrscheinlichkeit noch immer kleiner als 1. Der Fall "wird nicht gezogen" _kann_ vorkommen.

          Es kommt halt drauf an, ob da ein Client / ein Besucher auf das Ergebnis warten muß, oder ob es wirklich völlig egal ist, wie lange die Berechnung dauert.

          Die Wartezeit kann ins Unendliche gehen. Wenn ein Versuch eine Millisekunde dauert, ist _jede_ Millisekunde die Wahrscheinlichkeit wieder 59/60, dass die richtige Zahl _nicht_ gefunden wird. Auf Dauer gesehen ist es zwar unwahrscheinlich; aber es ist _nicht_ zwingend gegeben, dass der Algorithmus terminiert.

          Und bedenke bitte: Das Problem tritt nicht erst beim letzten Wert auf, sondern bereits beim zweiten.

          Cheatah

          1. Hallo Cheatah,

            Ja: 1/60. Die Wahrscheinlichkeit, bei n Ziehungen diesen Wert zu erhalten, beträgt _nicht_ n*1/60. Die Formel habe ich leider nicht mehr im Kopf (1-(1-1/60)^n?); aber nach n Versuchen ist die Wahrscheinlichkeit noch immer kleiner als 1. Der Fall "wird nicht gezogen" _kann_ vorkommen.

            So ein aehnliches Problem haben wir hier auch an einer Stelle. Auf der Download-Seite von SELFHTML werden ja bei jedem Aufruf immer 10 andere Adressen angeboten. Dazu muessen alle verfuegbaren Adressen eingelesen werden. 10 davon sollen per Zufall eingelesen werden. Dabei soll der Algorithmus aber so wasserdicht sein, dass er auch dann sauber arbeitet, wenn nur 10 Adressen als Ressource zur Verfuegung stehen, also alle verfuegbaren Adressen aufgelistet werden muessen, nur in beliebiger Reihenfolge. Christian hat dazu folgende Perl-Zeile produziert:

            push @new, splice(@resource_lines, rand @resource_lines, 1) while (@resource_lines && @new < 10);

            In @resource_lines sind die zeilenweise eingelesenen Adressen gespeichert. In @new soll der Array der 10 aufzulistenden Adressen erzeugt werden.

            while (@resource_lines && @new < 10)
            sorgt dafuer, dass @new so lange gefuettert wird, bis 10 Eintraege vorhanden sind oder keine eingelesenen Adressen mehr verfuegbar sind.

            Solange wird @new mit push etwas hinzugefuegt, und zwar der Rueckgabewert der splice-Funktion. So, wie splice dort mit Parametern versorgt wird, wird einfach ein zufaellig ausgewaehltes Element aus @resource_lines geloescht. Da splice das geloeschte Element zurueckgibt, ist dies ein brauchbarer zweiter Parameter fuer push. Da das verwendete Element gleichzeitig geloescht wird, ist beim naechsten Schleifendurchgang sichergestellt, dass es nicht mehr da ist (und also in der Ergebnisliste @new nicht doppelt auftauchen kann).

            Mit dieser Technik kann man finde ich Probleme der geschilderten Art ganz gut loesen.

            viele Gruesse
              Stefan Muenz

            1. Hi Stefan,

              Christian hat dazu folgende Perl-Zeile produziert:

              Christian, gib's zu - Du hast aus perldoc perlfaq4 geklaut ;-) (Und das ist gut so... dazu ist es schließlich da!)

              push @new, splice(@resource_lines, rand @resource_lines, 1) while (@resource_lines && @new < 10);

              Jupp. Genau dies, nur in extrem performanter Form, ist es, was ich vorgeschlagen habe: Solange zufällige Werte aus dem (leicht generierbaren) ursprünglichen Array nehmen und dem anschließend zufällig sortierten hinzufügen, bis das erste leer und das zweite voll ist. In JavaScript ist das vermutlich(?) nicht ganz so geschickt zu lösen; aber grundsätzlich ist der Algorithmus der gleiche.

              Cheatah

              1. Hallo Cheatah,

                Christian hat dazu folgende Perl-Zeile produziert:

                Christian, gib's zu - Du hast aus perldoc perlfaq4 geklaut ;-)

                Nein, aus einem Algorithmen-Buch ;-)

                push @new, splice(@resource_lines, rand @resource_lines, 1) while
                (@resource_lines && @new < 10);

                Jupp. Genau dies, nur in extrem performanter Form,

                Ja, die Performance ist hier in der Tat leider ein Problem: durch das
                splice() wird der Algorithmus sehr langsam. Da ist deine
                Implementierung wesentlich schneller, aber an dieser Stelle (dem
                Download-Script) war es relativ egal, ob das nun ein paar Ms schneller
                oder langsamer lief.

                Gruesse,
                 CK

    2. »»Tipp: Zufallswert plus Nachbearbeitung. Zufallswert ermitteln und nachsehen, ob diese Zahl schon gezogen wurde. Falls ja: verwerfen, falls nein: nehmen.

      Hi,
      nicht ganz (verwerfen), sondern einfach den nächsten freien nehmen.
      Auf diese Weise ist man nach 60 Schritten garantiert durch...

      Bye
      Wolfgang

      1. Hi Wolfgang,

        Tipp: Zufallswert plus Nachbearbeitung.
        Zufallswert ermitteln und nachsehen, ob
        diese Zahl schon gezogen wurde. Falls ja:
        verwerfen, falls nein: nehmen.
        Hi,
        nicht ganz (verwerfen), sondern einfach den
        nächsten freien nehmen.
        Auf diese Weise ist man nach 60 Schritten garantiert
        durch...

        ... und hat garantiert keine Gleichverteilung mehr.

        Notwendige Voraussetzung für die Gleichverteilung ist die Unabhängigkeit der Zufallsereignisse.

        Deine Änderung jedoch macht die sofortige Ziehung von Zahlen direkt hinter großen Lücken wahrscheinlicher als diejenige von deren direktem Nachfolger.

        So geht es also nicht ...

        Viele Grüße
              Michael

  3. Ich möchte ein Array mit 60 Elementen mit
    60 Zufallszahlen zwischen 0 und 59 , ohne redundante
    Werte erzeugen.
    Kann man mir helfen ??

    Hi again,

    also gut. Noch´n Versuch, nachdem mein erster Algorithmus bei Cheatah (unverständlicherweise) in Ungnade gefallen ist:

    step 1: ein Source-Array mit 60 Elementen erzeugen, jedes Element wird mit seinem Index gefüllt.
    step 2: ein Destin-Array mit 60 Elementen erzeugen und uninitialisiert lassen.
    step 3: mittels Math.random()*60 eine (Integer-) Zufallszahl zwischen 0 und 59 erzeugen das Ergebnis ist der Index in die Source-Tabelle. Der Wert des so selektierten Source-Array Elemtes ist der erste Wert für das Destin-Array.
    step 4a: Alle Elemente des Source-Array, beginnend mit dem ersten Wert _nach_ dem selektierten Element bis zum Ende des Arrays alle Elemente um eine Position nach vorne schieben. Der Wert des selektierten Elementes wird so eliminiert, die Tabelle wird ein Element kürzer.

    step 3 wiederholen, jedoch (mittels Math.random() * 59) eine Zufallszahl in einem nun kleineren Bereich erzeugen und damit das Source-Array referenzieren.
    step 4 wiederholen. Das zweite Destin-Array Element wird generiert, das Source-Array wird wieder kürzer

    step 3 und 4 so lange wiederholen, bis Source-Array kein Element und Destin-Array 60 Elemente enthält

    okay Cheatah ?

    Ciao
    Hans-peter

    1. Hallo,

      also gut. Noch´n Versuch, nachdem mein erster Algorithmus bei
      Cheatah (unverständlicherweise) in Ungnade gefallen ist:

      [...]

      Das ist doch derselbe Algorithmus, den Cheatah beschrieben hatte ;-)

      Gruesse,
       CK

      1. Hallo Christian

        Das ist doch derselbe Algorithmus, den Cheatah beschrieben hatte ;-)

        ääh ... ja. Stimmt. Jetzt wo´s Du´s sagst ...

        Hans-Peter

  4. Hi,

    Ich möchte ein Array mit 60 Elementen mit
    60 Zufallszahlen zwischen 0 und 59 , ohne redundante
    Werte erzeugen.
    Kann man mir helfen ??

    bei den bisherigen Antworten fällt mir auf, das kein Hinweis auf die mangelhafte Implementation der Zufälligkeitsfunktion von javascript erfolgt ist.
    Ein Algorythmus, der auf Math.random aufbaut, arbeitet nicht einwandfrei. Ab mehr als 16 Einträgen in einem Array kommt es sporadisch zu Aussetzern in der Generierung des Zufallswertes.
    In früheren Diskussionen wurde gerne darauf hin gewiesen.
    Beispiel: http://www.jelue.de/lotto_neu.htm
    Das Beispiel arbeitet mit 49 Einträgen im Array. Nach mehrmaligem Ausführen kommt es zu Problemen und die Logik versagt, weil kein gültiger Zufallswert erzeugt wurde. Beobachtet unter Netscape6.2 und IE ab 5.5.
    Von daher kommt es sehr auf den verfolgten Zweck an, ob man solch eine Funktionalität in eine Webseite einbaut.
    Gruß
    Günter

  5. Ich möchte ein Array mit 60 Elementen mit
    60 Zufallszahlen zwischen 0 und 59 , ohne redundante
    Werte erzeugen.
    Kann man mir helfen ??

    http://forum.de.selfhtml.org/archiv/2002/5/11158/#m61861