Fałszywe kości hazardzisty

26

Błąd gracza jest uprzedzeniem poznawczym, w którym błędnie spodziewamy się, że rzeczy, które miały miejsce, często będą mniej prawdopodobne w przyszłości, a rzeczy, które nie zaistniały od dłuższego czasu, prawdopodobnie będą miały miejsce wkrótce. Twoim zadaniem jest wdrożenie określonej wersji tego.

Wyzwanie Wyjaśnienie

Napisz funkcję, która zwraca losową liczbę całkowitą od 1 do 6 włącznie. Haczyk: przy pierwszym uruchomieniu funkcji wynik powinien być jednorodny (w granicach 1%), jednak każde kolejne wywołanie będzie przekrzywione na korzyść wartości, które rzuciło się wcześniej kilka razy. Szczegółowe informacje są następujące:

  • Kostka pamięta liczbę wygenerowanych do tej pory liczb.
  • Każdy wynik jest ważony według następującego wzoru: doountmzax-doountrejami+1
    • Na przykład, jeśli dotychczasowe liczby rzutów wynoszą [1,0,3),2),1,0] , wagi będą wynosić [3),4,1,2),3),4] , to znaczy, że będziesz 4 razy bardziej prawdopodobne, że wyrzuci 2) niż 3) .
    • Zauważ, że wzór oznacza, że ​​wynik rzutu [za,b,do,re,mi,fa] jest ważony tak samo jak [za+n,b+n,do+n,re+n,mi+n,fa+n]

Zasady i założenia

  • Obowiązują standardowe zasady we / wy i zakazane luki
  • Rzuty nie powinny być deterministyczne. (tzn. użyj PRNG z niestabilnego źródła, jak zwykle jest dostępne jako wbudowane).
  • Twoje losowe źródło musi mieć okres co najmniej 65535 lub być prawdziwą przypadkowością.
  • Rozkłady muszą zawierać się w granicach 1% dla wag do 255
    • 16-bitowe RNG są wystarczająco dobre, aby spełnić oba powyższe wymagania. Większość wbudowanych RNG jest wystarczająca.
  • Możesz przekazać aktualną dystrybucję, o ile rozkład ten jest albo mutowany przez wywołanie, albo dystrybucja po rzucie jest zwracana obok rzutu. Aktualizacja dystrybucji / zliczeń jest częścią tego wyzwania .
  • Możesz używać wag zamiast zliczeń. Robiąc to, ilekroć waga spadnie do 0, wszystkie ciężary powinny wzrosnąć o 1, aby osiągnąć taki sam efekt, jak liczenie zapasów.
    • Możesz użyć tych wag jako powtórzeń elementów w tablicy.

Powodzenia. Niech bajty będą zawsze na twoją korzyść.

Wołowina
źródło
Wygląda na to, że możesz zastosować się do wszystkich reguł i zablokować luki, zaczynając od losowej liczby n, a następnie generując (n ++% 6).
Faks
2
@ Faks Ten problem wyraźnie i dokładnie określa, jaki rozkład liczby $ k $ th należy podać pierwszym liczbom $ k-1 $. Twój pomysł daje oczywiście niewłaściwy rozkład dla drugiej liczby, biorąc pod uwagę pierwszą liczbę.
JiK
@JiK Nie zgadzam się, ponieważ argument ten może być użyty przeciwko dowolnemu innemu kodowi, który używa PRNG w przeciwieństwie do prawdziwego losowego. Moja propozycja to PRNG, choć bardzo uproszczona.
Faks
@JiK Zakładając, że mówisz o rozkładzie teoretycznym. Zmierzony rozkład mieści się w wymaganym 1% dla wystarczająco dużego $ k $, aby mieć znaczenie statystyczne.
Faks
1
@Fax Twoje losowe źródło nie ma okresu co najmniej 65535, więc PRNG nie wystarcza na ten problem. Nie rozumiem też, co masz na myśli przez „pomiar rozkładu”.
JiK

Odpowiedzi:

12

R , 59 bajtów

function(){T[o]<<-T[o<-sample(6,1,,max(T)-T+1)]+1
o}
T=!1:6

Wypróbuj online!

Utrzymuje liczenia w T, który jest następnie przekształcany do użycia jako weightsargument do sample(co następnie najprawdopodobniej normalizuje je do sumy 1).

[<<-Operatora do przypisania wartości do Tw jednym ze środowisk macierzyste (w tym przypadku tylko środowisko macierzysty jest .GlobalEnv).

Giuseppe
źródło
2
Ładne wykorzystanie globalnego zlecenia. Czy jest jakiś powód, dla którego wywołałeś zmienną T? (Oprócz tego, że kod jest trudniejszy do odczytania!)
Robin Ryder
@RobinRyder Wydaje mi się, że moim pierwotnym pomysłem było użycie tej funkcji Tlub Fwewnętrznie tej funkcji, a potem byłem zbyt leniwy, aby ją zmienić, gdy zdałem sobie sprawę, że potrzebuję globalnego przydziału.
Giuseppe
3
@RobinRyder: Dziwię się, że nie proponujesz rozwiązania Wang-Landau!
Xi'an
1
@ Xi'an Zacząłem pracować nad jednym! Ale liczba bajtów była o wiele za wysoka podczas używania pakietupawl .
Robin Ryder
6

Python 3 , 112 99 bajtów

from random import*
def f(C=[0]*6):c=choices(range(6),[1-a+max(C)for a in C])[0];C[c]+=1;print(c+1)

Wypróbuj online!

Wyjaśnienie

# we only need the "choice" function
from random import*

      # C, the array that holds previous choices, is created once when the function is defined
      # and is persisted afterwards unless the function is called with a replacement (i.e. f(C=[0,1,2,3,4,5]) instead of f() )
      C=[0]*6
# named function
def f(.......):
                  # generate weights
                  [1-a+max(C)for a in C]
# take the first item generated using built-in method
c=choices(range(6),......................)[0]
    # increment the counter for this choice
    C[c]+=1
    # since the array is 0-indexed, increase the number by 1 for printing
    print(c+1)

Edycja: Zapisano 13 bajtów. Dzięki, attinat !

Triggernometria
źródło
1
99 bajtów
attinat
@attinat Możesz upuścić 2 bajty, używając rozpakowywania krotek ( c,=i upuszczania [0]). Warto również zauważyć, że choicesjest to Python
3.6+
5

05AB1E , 13 bajtów

Z>αāDrÅΓΩ=Q+=

Wypróbuj online!

Pobiera listę zliczeń jako dane wejściowe. Wysyła rzut i nowe liczy się.

Wyjaśnienie:

Z                 # maximum
 >                # plus 1
  α               # absolute difference (vectorizes)
                  # the stack now has the list of weights
ā                 # range(1, length(top of stack)), in this case [1..6]
 D                # duplicate
  r               # reverse the entire stack
   ÅΓ             # run-length decode, using the weights as the run lengths
     Ω            # pick a random element
                  # the stack is now: counts, [1..6], random roll
=                 # output the roll without popping
 Q                # test for equality, vectorizing
  +               # add to the counts
   =              # output the new counts
Ponury
źródło
3

JavaScript (ES8), 111 bajtów

_=>++C[C.map((v,i)=>s+=''.padEnd(Math.max(...C)-v+1,i),s=''),n=s[Math.random()*s.length|0]]&&++n;[,...C]=1e6+''

Wypróbuj online!

W jaki sposób?

Jest to raczej naiwna i prawdopodobnie nieoptymalna implementacja, która przeprowadza symulację zgodnie z opisem.

dosjamzax(do)-doja+1

Arnauld
źródło
3

APL (Dyalog Unicode) , 32 bajty SBCS

-4 bajty przy użyciu replikacji zamiast indeksu interwału.

{1∘+@(⎕←(?∘≢⌷⊢)(1+⍵-⍨⌈/⍵)/⍳6)⊢⍵}

Wypróbuj online!

Zdefiniowane jako funkcja, która przyjmuje bieżący rozkład jako argument, drukuje wynikowy rzut matrycy i zwraca zaktualizowany rozkład. Pierwszy przebieg na TIO to 100 wywołań rozpoczynających się od [0,0,0,0,0,0], drugi przebieg jest silnie tendencyjny w kierunku 1 z [0,100,100,100,100,100], a ostatni przebieg jest silnie tendencyjny w kierunku 6 w ten sam sposób.

jastrząb
źródło
3

Perl 6 , 31 bajtów

{--.{$/=.pick}||++«.{1..6};$/}

Wypróbuj online!

Akceptuje bieżący rozkład ciężaru jako BagHash, zaczynając od tego, gdzie wszystkie ciężary wynoszą 1. Rozkład jest mutowany na miejscu.

Metoda BagHash pickwybiera losowo klucz przy użyciu powiązanych wag; waga tego klucza jest następnie zmniejszana o jeden. Jeśli w ten sposób waga jest zerowa, ++«.{1..6}zwiększa się masy wszystkich liczb 1-6.

Sean
źródło
2

JavaScript (ES6 +), 97 bajtów

d=[1,2,3,4,5,6]
w=[...d]
r=x=>(i=~~(Math.random()*w.length),k=w[i],w.concat(d.filter(x=>x!=k)),k)

Wyjaśnienie

d=[1,2,3,4,5,6]                   // basic die
w=[...d]                          // weighted die
r=x=>(                            // x is meaningless, just saves 1 byte vs ()
  i=~~(Math.random()*w.length),   // pick a random face of w
  k=w[i],                         // get the value of that face
  w.concat(d.filter(x=>x!=k)),    // add the faces of the basic die that aren't the value
                                  // we just picked to the weighted die
  k                               // return the value we picked
)

Warto zauważyć, że w końcu wysadzić jeśli wprzekracza długość 2 32 -1, co jest maksymalna długość tablicy w js, ale prawdopodobnie będziesz hit limit pamięci wcześniej, biorąc pod uwagę 32-bitową tablicę int 2 32 -1 długo 16GiB, a niektóre (większość?) Przeglądarek nie pozwalają na użycie więcej niż 4GiB.

asgalant
źródło
2

Perl 6 , 49 bajtów

{($!=roll (1..6 X=>1+max 0,|.{*})∖$_:),$_$!}

Wypróbuj online!

Bierze poprzednie rolki jako torbę (multiset). Zwraca nową rolkę i nową dystrybucję.

Wyjaśnienie

{                                            }  # Anon block taking
                                                # distribution in $_
                     max 0,|.{*}  # Maximum count
                   1+             # plus one
           1..6 X=>  # Pair with numbers 1-6
          (                     )∖$_  # Baggy subtract previous counts
     roll                            :  # Pick random element from Bag
 ($!=                                 )  # Store in $! and return
                                       ,$_$!  # Return dist with new roll
nwellnhof
źródło
1

Pyth , 22 20 bajtów

Xt
hOs.e*]kh-eSQbQQ1

Wypróbuj online!

Dane wejściowe to poprzednie częstotliwości w postaci listy, dane wyjściowe następnego rzutu i zaktualizowane częstotliwości są oddzielone znakiem nowej linii.

Xt¶hOs.e*]kh-eSQbQQ1   Implicit: Q=eval(input())
                       Newline replaced with ¶
      .e         Q     Map elements of Q, as b with index k, using:
             eSQ         Max element of Q (end of sorted Q)
            -   b        Subtract b from the above
           h             Increment
        *]k              Repeat k the above number of times
                       Result of the above is nested weighted list
                       e.g. [1,0,3,2,1,0] -> [[0, 0, 0], [1, 1, 1, 1], [2], [3, 3], [4, 4, 4], [5, 5, 5, 5]]
     s                 Flatten
    O                  Choose random element
   h                   Increment
  ¶                    Output with newline
 t                     Decrement
X                 Q1   In Q, add 1 to the element with the above index
                       Implicit print
Sok
źródło
1

Galaretka , 12 bajtów

’ạṀJx$X,Ṭ+¥¥

Wypróbuj online!

Łącze monadyczne, które pobiera pojedynczy argument, bieżącą listę zliczeń i zwraca listę wybranych liczb oraz zaktualizowaną listę zliczeń.

Galaretka , 18 bajtów

0x6+ɼṀ_®‘Jx$XṬ+ɼṛƊ

Wypróbuj online!

Alternatywnie, oto link niladyczny, który zwraca wybrany numer i śledzi listę zliczeń w rejestrze.

Nick Kennedy
źródło