Игральные кости игрока


26

Ошибка игрока - это когнитивное искажение, в котором мы ошибочно ожидаем, что случившееся часто будет менее вероятным в будущем, а то, что не произошло через некоторое время, с большей вероятностью произойдет в ближайшее время. Ваша задача - реализовать конкретную версию этого.

Объяснение проблемы

Напишите функцию, которая возвращает случайное целое число от 1 до 6 включительно. Подвох: при первом запуске функции результат должен быть равномерным (в пределах 1%), однако каждый последующий вызов будет перекошен в пользу значений, которые были свернуты меньшее количество раз ранее. Конкретные детали заключаются в следующем:

  • Жребий запоминает количество сгенерированных на данный момент чисел.
  • Каждый результат взвешивается по следующей формуле:countmaxcountdie+1
    • Например, если количество бросков до сих пор составляет , веса будут , то есть вы будете В 4 раза больше шансов бросить чем .[1,0,3,2,1,0][3,4,1,2,3,4]23
    • Обратите внимание, что формула означает, что результат броска взвешивается так же, как[a,b,c,d,e,f][a+n,b+n,c+n,d+n,e+n,f+n]

Правила и предположения

  • Применяются стандартные правила ввода / вывода и запрещенные лазейки
  • Ролики не должны быть детерминированными. (т. е. используйте PRNG, посеянный из энергозависимого источника, который обычно доступен как встроенный.)
  • Ваш случайный источник должен иметь период не менее 65535 или быть истинной случайностью.
  • Распределения должны быть в пределах 1% для веса до 255
    • 16-битные RNG достаточно хороши, чтобы удовлетворить оба вышеуказанных требования. Достаточно большинства встроенных ГСЧ.
  • Вы можете передать текущее распределение, если это распределение либо мутирует по вызову, либо распределение после броска возвращается вместе с броском штампа. Обновление дистрибутива / количества является частью этой проблемы .
  • Вы можете использовать вес вместо подсчета. При этом всякий раз, когда вес падает до 0, все веса должны увеличиваться на 1 для достижения того же эффекта, что и при подсчете веса.
    • Вы можете использовать эти веса в качестве повторений элементов в массиве.

Удачи. Пусть байты всегда будут в твою пользу.


Похоже, что вы можете соблюдать все правила и запрещенные лазейки, начав со случайного числа n, а затем выведя (n ++% 6).
Факс

2
@Fax Эта задача явно и точно указывает, какому распределению $ k $ -го числа следует дать первые $ k-1 $ числа. Ваша идея, очевидно, дает неправильное распределение для второго числа, данного первого числа.
JiK

@JiK Я не согласен, так как этот аргумент может быть использован против любого другого кода, который использует PRNG, а не случайно. Мое предложение - PRNG, хотя и очень упрощенное.
Факс

@JiK Если вы говорите о теоретическом распределении, то есть. Измеренное распределение находится в пределах требуемого 1% для достаточно большого $ k $, чтобы иметь статистическую значимость.
Факс

1
@Fax Ваш случайный источник не имеет периода не менее 65535, поэтому для этой проблемы недостаточно ГРП. Кроме того, я не понимаю , что вы имеете в виду под «измеренным распределением».
JiK

Ответы:


12

R , 59 байт

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

Попробуйте онлайн!

Сохраняет количество T, которое затем преобразуется для использования в качестве weightsаргумента sample(что затем, скорее всего, нормализует их для суммирования 1).

[<<-Оператор используется для присвоения значения Tв одной из родительских сред (в данном случае, единственный родитель среда .GlobalEnv).


2
Хорошее использование глобального назначения. По какой причине вы назвали свою переменную T? (Помимо того, что код становится труднее читать!)
Робин Райдер

@RobinRyder Я думаю, что моя первоначальная идея заключалась в том, чтобы использовать эту функцию Tили Fвнутренне для этой функции, а потом мне было лень ее менять, когда я понял, что мне нужно глобальное назначение.
Джузеппе

3
@RobinRyder: Я удивлен, что вы не предлагаете решение Ван-Ландау!
Сиань

1
@ Сиань, я начал работать над одним! Но количество байтов было слишком велико при использовании пакета pawl.
Робин Райдер

6

Python 3 , 112 99 байт

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)

Попробуйте онлайн!

объяснение

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

Изменить: Сохранено 13 байт. Спасибо, attinat !



@attinat Вы можете удалить 2 байта, используя распаковку кортежей ( c,=и удаление [0]). Также стоит отметить, что choicesэто Python 3.6+
409_Conflict

5

05AB1E , 13 байтов

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

Попробуйте онлайн!

Принимает список отсчетов в качестве входных данных. Выводит рулон и новые счета.

Объяснение:

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

3

JavaScript (ES8), 111 байт

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

Попробуйте онлайн!

Как?

Это довольно наивная и, скорее всего, неоптимальная реализация, которая выполняет моделирование, как описано.

Мы продолжаем отслеживать граф в . На каждом броске мы строим строку состоящую из каждого кубика, который повторял раз, и выбираем случайную запись там с равномерным распределением.Csimax(C)Ci+1


3

APL (Dyalog Unicode) , 32 байта SBCS

-4 байта с использованием репликации вместо интервала индекса.

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

Попробуйте онлайн!

Определяется как функция, которая принимает текущее распределение в качестве аргумента, печатает полученный бросок кубика и возвращает обновленное распределение. Первый запуск на TIO - это 100 вызовов, начиная с [0,0,0,0,0,0], второй запуск сильно смещен в сторону 1 с [0,100,100,100,100,100], а последний запуск сильно смещен в сторону 6 таким же образом.


3

Perl 6 , 31 байт

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

Попробуйте онлайн!

Принимает текущее распределение веса как BagHash, начиная с единицы, где все веса равны 1. Распределение мутирует на месте.

Метод BagHash pickвыбирает ключ случайным образом, используя соответствующие веса; вес этого ключа затем уменьшается на единицу. Если этот вес становится равным нулю, ++«.{1..6}увеличивается вес всех чисел 1-6.



2

Javascript (ES6 +), 97 байт

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)

объяснение

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
)

Обратите внимание, что это в конечном итоге взорвется, если wпревысит длину 2 32 -1, что является максимальной длиной массива в js, но вы, вероятно, достигнете предела памяти до этого, учитывая, что 32-битный массив int 2 32 -1 длиной 16 ГБ, а некоторые (большинство?) Браузеры не позволяют использовать более 4 ГБ.


2

Perl 6 , 49 байт

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

Попробуйте онлайн!

Принимает предыдущие рулоны как Мешок (мультимножество). Возвращает новый рулон и новый дистрибутив.

объяснение

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

1

Pyth , 22 20 байт

Xt
hOs.e*]kh-eSQbQQ1

Попробуйте онлайн!

Ввод - это предыдущие частоты в виде списка, выводит следующий бросок и обновленные частоты, разделенные новой строкой.

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

1

Желе , 12 байт

’ạṀJx$X,Ṭ+¥¥

Попробуйте онлайн!

Монадическая ссылка, которая принимает один аргумент, текущий список счетчиков и возвращает список выбранного числа и обновленный список счетчиков.

Желе , 18 байт

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

Попробуйте онлайн!

В качестве альтернативы, вот нильадная ссылка, которая возвращает выбранное число и отслеживает список счетчиков в регистре.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.