Würfel aus dem Wechsel des Zufallsgenerators

10

Einführung

Sie erhalten einen zufälligen Ganzzahlgenerator mit der folgenden Implementierung

  • Der erste Aufruf gibt immer 1 zurück.
  • Der zweite Aufruf gibt eine zufällige Ganzzahl zwischen 1 und 2 zurück.
  • Der dritte Aufruf gibt eine zufällige Ganzzahl zwischen 1 und 3 zurück.
  • Der n-te Aufruf gibt eine zufällige Ganzzahl zwischen 1 und n einschließlich zurück.

Schreiben Sie basierend auf der obigen Funktion einen Zufallswürfelgenerator, der vollkommen zufällig ist und mit gleicher Wahrscheinlichkeit einen Wert zwischen 1 und 6 (einschließlich) zurückgibt.

Regeln

  • Ihr Programm / Ihre Funktion sollte zu einer zufälligen Ganzzahl zwischen 1 und 6 führen, einschließlich in einer verwendbaren Form, dh zur Standardausgabe oder als Funktionsrückgabewert.
  • Der obige Generator für aufsteigende Zufallszahlen kann als "freie" Funktion in Ihrem Programm definiert werden (dh zählt nicht für Ihre Zeichenanzahl) oder als separates Skript / Programm, das nach Bedarf ausgeführt wird, vorausgesetzt, der Status ( n) ist dauerhaft zwischen Anrufen.
  • Angenommen, in einem einzigen Anwendungsfall Ihres Programms werden niemals mehr als 1000 Würfelwürfe angefordert, und der anfängliche Zufallszahlengenerator kann 1auf das Ende von 1000 Würfeln zurückgesetzt werden, um ein Überlaufen von zu vermeiden n.
  • Ihr Programm verwendet möglicherweise keine andere Zufallszahlenquelle als den oben definierten aufsteigenden Zufallsgenerator. Sie können natürlich mehrere Zufallszahlen vom Zufallszahlengenerator für jede einzelne Würfelwurfausgabe anfordern.
  • Dies ist Code-Golf, daher ist der Gewinner die kürzeste Antwort oder die meisten Stimmen im Falle eines Unentschieden. Wenn Sie 1000 Würfelwürfe mit weniger als 1000 generierten Zufallszahlen generieren können, geben Sie sich einen 10-Punkte-Effizienzbonus .

Beispiel

./asc-rand
1 # random integer between 1 and 1
./asc-rand
1 # random integer between 1 and 2
./asc-rand
3 # random integer between 1 and 3
./asc-rand
4 # random integer between 1 and 4

# dice-gen generates random dice based on output of asc-rand program.
./dice-gen
3
./dice-gen
6
./dice-gen
5
./dice-gen
1
mellamokb
quelle
Ist das Programm iterate(6):b=asc-rand(); print billegal oder funktioniert es nicht? Ich könnte die dritte Regel falsch verstehen.
beary605
@ beary605: Der Zufallszahlengenerator kann nur nach den gesamten 1000 Würfeln zurückgesetzt werden, nicht zwischen jedem Würfelwurf. Der einzige Grund, den ich erwähne, der sich mit möglichen Überläufen des vom Zufallszahlengenerator zurückgegebenen Werts befasst, ist nicht eines der Probleme bei dieser Herausforderung. Bearbeiten: Ich habe den Zweck der Regel geklärt, hoffe es hilft.
Mellamokb
Wenn Sie "Zufallszahl" sagen, meinen Sie "zufällige Ganzzahl" oder "zufällige (abgeschnittene) reelle Zahl"? Vielleicht gibt es eine Konvention, die mir nicht bekannt ist.
DavidC
@ DavidCarraher: Sehr guter Punkt. Ich meinte zufällige Ganzzahl und ich sehe, dass das nicht klar ist. Ich werde die Frage aktualisieren. Bearbeiten: Aktualisiert.
Mellamokb
1
Dürfen wir den Randomizer fragen, wie oft er Zufallszahlen generiert hat? Ich hatte den Eindruck, dass wir nicht konnten.
Matt

Antworten:

2

J - 13 char

Dies macht die gleichen Annahmen wie bei Golfscript: Die Anzahl der Würfel ist in Standard und wir listen die Würfelwürfe auf, die herauskommen sollen.

r=:1+?  NB. free random function
r>:i.".1!:1]1

Erklärt durch Explosion:

r=:1+?           NB. r(x) = 1 + a random number between 0 and n-1
           ]1    NB. input file handle
       1!:1      NB. read in a string
     ".          NB. convert to integer
 >:i.            NB. make a list of numbers, from 1 to that integer
r                NB. apply the random function

Wenn das irgendwie unbefriedigend ist, gibt es hier ein längeres Programm mit 21 Zeichen, mit f''dem Zufallszahlen generiert werden können, die einen Status und alles enthalten.

r=:1+?  NB. free random function
c=:0
f=:3 :'r c=:1+c'
Algorithmushai
quelle
K Analoga: freie Zufallsfunktion r:{*1_draw x}, Standardversion (10 Zeichen) r'1+!. 0:` , Funktionsversion (14 Zeichen), c:0;f:{r@c+:1}aufgerufen von f[].
Algorithmushai
6

Python, 31 Zeichen

Definieren Sie den Generator ähnlich wie beim Scleaver wie folgt:

from random import randint
n=0
def r():
    global n;n+=1
    return randint(1,n)

Dann eine Funktion zum Zurückgeben von Würfeln:

D=lambda:eval('r(),'*6)[-1]%6+1

Rufen Sie D()jederzeit an, wenn Sie einen gleichmäßig zufälligen Würfelwurf benötigen.

Keith Randall
quelle
Ah, kluger Gebrauch von eval, ich mag es.
Scleaver
3

Scala 23

def s={r;r;r;r;r;r%6+1}

Die Methode r kann (ca.) folgendermaßen implementiert werden:

var cnt = 0 
val rnd = new util.Random 

def r = {
  cnt %= 1000
  cnt += 1
  rnd.nextInt (cnt)
}

ein grober Test:

scala> (1 to 6).map (i => ((1 to 600) map (_=>s)).filter (_ == i).size)
res26: scala.collection.immutable.IndexedSeq[Int] = Vector(110, 105, 91, 96, 106, 102)

Jeder 6. Aufruf sollte eine gleichmäßige Verteilung über die 6 Werte ergeben, also werfe ich 5 weg.

Benutzer unbekannt
quelle
2

GolfScript (15 Zeichen)

Dies setzt voraus, dass die Anzahl der erforderlichen Rollen auf stdin angegeben ist, und listet so viele Ergebnisse auf, die stdout liefert.

# The free increasing random function
0:N;{N):N rand)}:r;

~{r{;r}5*6%)n}*

Online-Demo

Ich könnte zwar den 10-Punkte-Bonus erhalten, wenn ich weniger als 1000 Würfe verwende, um 1000 Zahlen zu generieren, aber es würde mich weit mehr als 10 Zeichen kosten. Der triviale Ansatz, eine geeignete Entropie zu extrahieren, wenn N ein Vielfaches einer Potenz von 2 oder 3 ist, ist nicht ausreichend, da die Anzahl der verfügbaren Ergebnisse mod 3 nur 333 + 111 + 37 + 12 + 4 + 1 = 498 beträgt Nehmen Sie einen Sample-and-Reject-Ansatz. Mit diesem Ansatz können Sie erwartete 2242 Rollen von 1000 Anrufen bis erhalten r, aber die Buchhaltung verursacht zusätzlichen Aufwand und baseist ein sehr langer Funktionsname.

Peter Taylor
quelle
5
"und baseist ein sehr langer Funktionsname" Sie verwenden anscheinend Mathematica nicht . Wir bekommen solche Wunder wie NegativeBinomialDistribution, ExponentialGeneratingFunction, MathieuCharacteristicExponent, InverseFourierSequenceTransform, und SemialgebraicComponentInstances. :-)
Mr.Wizard
1

Python 65 63

i=7
while i>5:[R()for x in range(9)];i=int(`R()`[-1])
print i+1

Die Funktion R()ist der aufsteigende Randomizer.

Verwendungszweck:

$ ./rollDice.py
3
$ ./rollDice.py
5
Matt
quelle
Warum nicht deine forSchleife loswerden und nur Reinmal vor deiner whileSchleife aufrufen ?
Keith Randall
@KeithRandall Die Zahl, die ich als Würfelwurf zurückgebe, ist die letzte Ziffer der Zahl, die der aufsteigende Generator zurückgibt. Ich muss 10 Anrufe beim aufsteigenden Generator tätigen, um gleiche Wahrscheinlichkeiten für alle möglichen Ziffern sicherzustellen.
Matt
Warum 10 Anrufe? Wenn der Generator zufällig ist, sollte nicht jeder Aufruf im Prinzip die gleiche Wahrscheinlichkeit für eine der (zehn) Ziffern bieten? In der Praxis können Sie natürlich nur erwarten, dass sich für jede der Zahlen die gleiche Anzahl nähert.
DavidC
@DavidCarraher Der Generator gibt Zufallszahlen von 1 bis n zurück, wobei n die Häufigkeit ist, mit der Sie ihn aufgerufen haben. Ich schaue auf die letzte Ziffer dieser zurückgegebenen Nummer. Wenn n kein ganzzahliges Vielfaches von 10 ist, ist die Wahrscheinlichkeit nicht einheitlich. Zum Beispiel: Wenn n = 13 ist, werden die Wahrscheinlichkeiten wie folgt aufgeteilt: 1/9 für die Rollen 1,5,6 und 2/9 für die Rollen 2,3,4
Matt
@Matt: Ich nahm an R(), dass ein Float zurückgegeben wurde und Sie die niedrigstwertige Ziffer ergriffen haben . Nachdem klargestellt wurde, dass R()eine Ganzzahl zurückgegeben wird, ist dies sinnvoll.
Keith Randall
1

Python, 56

r ist definiert als:

from random import randint
n=0
def r(z):
    global n;n+=1
    return randint(1,n)

der Würfelgenerator d:

import math;d=lambda:math.ceil(6.*r(r(r(r(r(r(0))))))/n)

Verwendung, zB für 100 Rollen:

for i in range(100):print d()
Scleaver
quelle
Sie können das wahrscheinlich löschen , import mathwenn Sie ersetzen math.ceil(...)mitint(...)+1
Matt
Ich würde, aber es würde 7 als mögliche Ausgabe produzieren.
Scleaver
Oh ja. Das habe ich vermisst.
Matt
mellamokb klärte eine Frage, die ich über den aufsteigenden Randomizer hatte. Du darfst nicht nach n fragen.
Matt
1

Mathematica 51

Der Zufallszahlengenerator rwird zurückgesetzt, indem die globale Variable nauf 1 gesetzt wird.

n = 1; r[c_] := RandomInteger[{1, c}]

Code

Nicht im Rennen um den kürzesten Code ...

h := (n++; If[n < 4 \[Or] (y = r@n) > 6 Quotient[n, 6], h, y~Mod~6 + 1])

Verwendungszweck

t = Table[h, {60000}];
n
SortBy[Tally[t], First]

60000 Würfelwürfe erforderten 60031 Aufrufe an h. Tallyzeigt die Aufteilung nach den Nummern 1-6.

60031

{{1, 9923}, {2, 9966}, {3, 10016}, {4, 10028}, {5, 10009}, {6, 10058}}

DavidC
quelle
1

Perl, 22 oder 45

Implementierung des aufsteigenden Zufallszahlengenerators:

my $n=0;
sub r { $n++; return 1+int(rand$n); }

Erstellen:

#copy of the Scala solution; short code; uses 6N rolls
sub s{r;r;r;r;r;1+r%6}
#more efficient implementation, uses approximately 6+N+lnN rolls
sub roll { do{$a=r-1}while($a>$n-$n%6);return 1+(1+$a)%6 }

Austesten:

n Zahl chisquare
1 10001867 0,348569
2 10004853 2.355161
3 9994395 3.141602
4 10000177 0,003133
5 9999227 0,059753
6 9999481 0,026936
T 60000000 5.935154
60000000 Würfelwürfe dauerten 60000042 Aufrufe an r und 570,432735 Sekunden
o_o
quelle
0

x86-Opcode, 15 Bytes

f:  mov cx, 6
    call r ; return in AX
    loop $-3
    cwd
    div word [f+1]
    inc dx
    ret ; return in DX
14 m2
quelle
Anscheinend ist dies ein Beitrag von geringer Qualität?
Muhammad Salman
0

GolfScript , 8 Bytes

f;3f*f(-

Probieren Sie es online aus!

Es schaltet den Generator einmal ein und entfernt dann das Ergebnis. Dann würfelt es f2 und multipliziert es mit 3 (3 oder 6), subtrahiert dann f3-1 (0, 1, 2), was zu (3-2, 3-1, 3-0) oder (6-2, führt). 6-1, 6-0) W5.

Golfscript und die Zufallsfunktion existierten, bevor diese Frage gestellt wurde, ebenso wie eine rechtliche Einreichung.

Dies ist die einmalige Übermittlung. Wenn Sie es mehrmals in einem Anruf ausführen müssen,

GolfScript , 12 Bytes

f;3f*f-)0:i;

Probieren Sie es online aus!

Dadurch wird Ihr i-Aufruf auf 0 zurückgesetzt, sodass er entsprechend zurückgesetzt wird. Diese TIO zeigt 50 zufällige Ergebnisse.

Mathgeek
quelle
0

C (gcc) , 31 Bytes

f(i){for(i=5;i--;)c;i=~-c%6+1;}

Alle 6 Anrufe ist die Wahrscheinlichkeit, dass jede Nummer zwischen 1 und einschließlich 6 generiert wird, gleich.

cist #defined als Aufruf einer Funktion, die die perfekten Zufallszahlen erzeugt.

Probieren Sie es online aus!

SS Anne
quelle