Kości ze zmieniającego się losowego generatora

10

Wprowadzenie

Otrzymujesz losowy generator liczb całkowitych z następującą implementacją

  • Pierwsze wywołanie zawsze zwraca 1.
  • Drugie wywołanie zwraca losową liczbę całkowitą od 1 do 2.
  • Trzecie wywołanie zwraca losową liczbę całkowitą od 1 do 3.
  • N-te wywołanie zwraca losową liczbę całkowitą od 1 do n włącznie.

Opierając się na powyższej funkcji, napisz losowy generator kości, który jest całkowicie losowy, zwracając wartość od 1 do 6 (włącznie) z jednakowym prawdopodobieństwem.

Zasady

  • Twój program / funkcja powinna dać losową liczbę całkowitą od 1 do 6 włącznie, w pewnej użytecznej formie, tj. Do standardowego wyjścia lub jako wartość zwracaną przez funkcję.
  • Generator rosnących liczb losowych powyżej można zdefiniować jako „darmową” funkcję w twoim programie (tj. Nie liczy się do liczby znaków) lub jako osobny skrypt / program, który jest wykonywany w razie potrzeby, zakładając, że stan ( n) jest trwały między połączeniami.
  • Załóżmy, że w jednym przypadku użycia twojego programu nigdy nie będzie wymagane więcej niż 1000 rzutów kości, a początkowy generator liczb losowych można zresetować 1na końcu 1000 rzutów kości, aby uniknąć przepełnienia n.
  • Twój program nie może używać żadnego innego źródła liczb losowych, z wyjątkiem rosnącego generatora losowego zdefiniowanego powyżej. Możesz oczywiście poprosić o wiele losowych liczb z generatora liczb losowych dla każdego wyniku rzutu pojedynczymi kostkami.
  • To jest golf golfowy, więc zwycięzca jest najkrótszą odpowiedzią lub większością głosów w przypadku remisu. Jeśli możesz wygenerować 1000 rzutów kostką przy użyciu mniej niż 1000 losowych liczb, daj sobie 10-punktowy bonus wydajności .

Przykład

./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
źródło
Czy program jest iterate(6):b=asc-rand(); print bnielegalny czy nie działa? Mogę nie rozumieć trzeciej zasady.
beary605
@ beary605: Generator liczb losowych można zresetować tylko po całym rzucie 1000 kości, a nie między każdym rzutem kości. Jedyny powód, o którym wspomniałem, to takie radzenie sobie z możliwymi przelewami wartości zwracanej przez generator liczb losowych, nie jest jednym z problemów w tym wyzwaniu. Edycja: Wyjaśniłem cel reguły, mam nadzieję, że to pomoże.
mellamokb
Kiedy mówisz „liczba losowa”, masz na myśli „losową liczbę całkowitą” czy „losową (skróconą) liczbę rzeczywistą”? Być może istnieje jakaś konwencja, o której nie wiem.
DavidC
@DavidCarraher: Bardzo dobry punkt. Miałem na myśli losową liczbę całkowitą i widzę, że to nie jest jasne. Zaktualizuję pytanie. Edytuj: zaktualizowano.
mellamokb
1
Czy wolno nam zapytać randomizatora, ile razy wygenerował losowe liczby? Miałem wrażenie, że nie możemy.
Matt

Odpowiedzi:

2

J - 13 znaków

Przyjmuje to te same założenia co w Golfscript: że liczba kości jest w stdin i podajemy rzuty kostkami, które mają wyjść.

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

Wyjaśnione przez wybuch:

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

Jeśli jest to w jakiś sposób niezadowalające, oto dłuższy, 21-znakowy program, który można wywołać w f''celu wygenerowania liczb losowych, zawierających stan i wszystko.

r=:1+?  NB. free random function
c=:0
f=:3 :'r c=:1+c'
algorytmshark
źródło
K analogi: dowolna losowa funkcja r:{*1_draw x}, wersja stdin (10 znaków) r'1+!. 0:` , wersja funkcji (14 znaków) c:0;f:{r@c+:1}wywoływana przez f[].
algorytmshark
6

Python, 31 znaków

Podobnie jak scleaver, zdefiniuj generator tak:

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

Następnie funkcja zwracania rzutów kostką:

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

Dzwoń, D()gdy potrzebujesz równomiernie losowego rzutu kostką.

Keith Randall
źródło
Ach, sprytne użycie eval, podoba mi się.
scleaver,
3

Scala 23

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

Metoda r może być (w przybliżeniu) zaimplementowana w następujący sposób:

var cnt = 0 
val rnd = new util.Random 

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

trudny 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)

Co szóste połączenie powinno dawać równy rozkład między 6 wartościami, więc wyrzucam 5.

nieznany użytkownik
źródło
2

GolfScript (15 znaków)

Zakłada się, że wymagana liczba rolek jest podana na stdin, i podaje liczbę wyników do stdout.

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

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

Demo online

Chociaż mógłbym uzyskać premię 10 punktów za użycie mniej niż 1000 rzutów do wygenerowania 1000 liczb, kosztowałoby mnie to znacznie więcej niż 10 znaków. Trywialne podejście do wyodrębnienia odpowiedniej entropii, gdy N jest wielokrotnością potęgi 2 lub 3, jest zbyt krótkie, ponieważ liczba dostępnych wyników mod 3 wynosi tylko 333 + 111 + 37 + 12 + 4 + 1 = 498. Dlatego konieczne jest podejmij próbę i odrzuć. Dzięki takiemu podejściu można uzyskać 2242 rzuty z 1000 wywołań r, ale księgowanie basewiąże się z dodatkowymi kosztami i jest bardzo długą nazwą funkcji.

Peter Taylor
źródło
5
„i basejest bardzo długą nazwą funkcji” Najwyraźniej nie używasz Mathematica . Dostajemy takie cuda jak NegativeBinomialDistribution, ExponentialGeneratingFunction, MathieuCharacteristicExponent, InverseFourierSequenceTransform, i 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

Ta funkcja R()to rosnący randomizator.

Stosowanie:

$ ./rollDice.py
3
$ ./rollDice.py
5
Matt
źródło
Dlaczego nie pozbyć się forpętli i po prostu zadzwonić Rprzed nią while?
Keith Randall
@KeithRandall Liczba, którą zwracam podczas rzutu kostką, jest ostatnią cyfrą liczby zwracanej przez rosnący generator. Muszę wykonać 10 połączeń z rosnącym generatorem, aby zapewnić równe prawdopodobieństwo dla wszystkich możliwych cyfr.
Matt
Dlaczego 10 połączeń? Zasadniczo, jeśli generator jest losowy, czy każde połączenie nie powinno oferować jednakowego prawdopodobieństwa dla dowolnej (dziesięciu) cyfr? Oczywiście w praktyce można oczekiwać, że zbliży się do równej liczby dla każdej liczby.
DavidC,
@DavidCarraher Generator zwraca losowe liczby od 1 do n, gdzie n jest liczbą wywołań. Patrzę na ostatnią cyfrę tego zwróconego numeru. Jeśli n nie jest wielokrotnością całkowitą 10, prawdopodobieństwo nie będzie jednakowe. Na przykład: jeśli n = 13, prawdopodobieństwa zostaną podzielone w następujący sposób: 1/9 dla rzutów 1,5,6 i 2/9 dla rzutów 2,3,4
Matt
@Matt: Zakładałem, że R()zwraca liczbę zmiennoprzecinkową, a ty chwytałeś najmniej znaczącą cyfrę. Teraz, gdy wyjaśniono, że R()zwraca liczbę całkowitą, ma to sens.
Keith Randall
1

Python, 56

r jest zdefiniowane jako:

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

generator kości d:

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

użycie, np. na 100 rolek:

for i in range(100):print d()
scleaver
źródło
prawdopodobnie można usunąć import math, jeśli zastąpi math.ceil(...)sięint(...)+1
Matt
Zrobiłbym to, ale dałoby 7 jako możliwy wynik.
scleaver,
O tak. Tęsknie za tym.
Matt
mellamokb wyjaśnił moje pytanie dotyczące rosnącego randomizatora. Nie możesz poprosić o n.
Matt
1

Mathematica 51

Generator liczb losowych rjest resetowany przez ustawienie zmiennej globalnej nna 1.

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

Kod

Nie działa dla najkrótszego kodu ...

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

Stosowanie

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

60000 rzutów kości wymagało 60031 połączeń z h. Tallypokazuje podział według liczb 1-6.

60031

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

DavidC
źródło
1

Perl, 22 lub 45

Wdrożenie rosnącego generatora liczb losowych:

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

Generowanie:

#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 }

Testowanie:

n numer 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 rzutów kostką wymagało 60000042 połączeń na ri 570,432735 sekund
o_o
źródło
0

kod operacji x86, 15 bajtów

f:  mov cx, 6
    call r ; return in AX
    loop $-3
    cwd
    div word [f+1]
    inc dx
    ret ; return in DX
l4m2
źródło
Najwyraźniej jest to post niskiej jakości?
Muhammad Salman
0

GolfScript , 8 bajtów

f;3f*f(-

Wypróbuj online!

Wyskakuje generator raz, a następnie pozbywa się wyniku. Następnie rzuca f2 i mnoży go przez 3 (3 lub 6), a następnie odejmuje f3-1 (0, 1, 2), co daje (3-2, 3-1, 3-0) lub (6-2, 6-1, 6-0) W5.

Golfscript i funkcja losowa istniały przed opublikowaniem tego pytania, podobnie jak zgłoszenie prawne.

Jest to przesłanie jednorazowe. Jeśli musisz uruchomić go kilka razy w jednym połączeniu,

GolfScript , 12 bajtów

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

Wypróbuj online!

Spowoduje to zresetowanie twojego połączenia i do 0, więc odpowiednio zresetuje się. To TIO pokazuje 50 losowych wyników.

Mathgeek
źródło
0

C (gcc) , 31 bajtów

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

Co 6 połączeń prawdopodobieństwo wygenerowania każdej liczby od 1 do 6 włącznie jest równe.

cjest #defined jako wywołanie funkcji, która generuje idealne liczby losowe.

Wypróbuj online!

SS Anne
źródło