Кістки від зміни випадкового генератора


10

Вступ

Вам дається генератор випадкових цілих чисел із наступною реалізацією

  • Перше виклик завжди повертає 1.
  • Другий виклик повертає випадкове ціле число між 1 і 2.
  • Третя виклик повертає випадкове ціле число між 1 і 3.
  • П'яте виклик повертає випадкове ціле число між 1 і n включно.

Виходячи з вищенаведеної функції, запишіть генератор випадкових кісток, який є абсолютно випадковим, повертаючи значення між 1 і 6 (включно) з однаковою ймовірністю.

Правила

  • Ваша програма / функція повинна призвести до випадкового цілого числа від 1 до 6, включно, в якомусь використаному вигляді, тобто до стандартного виводу або як повернення функції.
  • Зростаючий генератор випадкових чисел вище може бути визначений як "вільна" функція у вашій програмі (тобто не враховується до вашого числа символів), або окремий сценарій / програма, яка виконується за необхідності, припускаючи, що стан ( n) є стійким між дзвінками.
  • Припустимо, що в одному випадку використання вашої програми ніколи не буде запитуватися більше 1000 рулонів з кістки, і початковий генератор випадкових чисел може бути скинутий до 1кінця 1000 рулонів кісток, щоб уникнути переповнення n.
  • Ваша програма може не використовувати будь-яке інше джерело випадкових чисел, крім висхідного випадкового генератора, визначеного вище. Ви, звичайно, можете вимагати декількох випадкових чисел від генератора випадкових чисел для кожного випуску одного колу.
  • Це код-гольф, тож переможець - найкоротша відповідь або більшість голосів у разі вирівнювання. Якщо ви можете генерувати 1000 рулонів з кістки, використовуючи менше 1000 генерованих випадкових чисел, надайте собі 10-бальний бонус ефективності .

Приклад

./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

Програма iterate(6):b=asc-rand(); print bнезаконна чи не працює? Можливо, я неправильно розумію третє правило.
beary605

@ beary605: Генератор випадкових чисел може бути скинутий лише після того, як буде зібрано цілих 1000 кісток, а не між кожним колом. Єдина причина, яку я згадую, що так мати справу з можливими переповненнями значення, поверненого генератором випадкових чисел, не є однією з проблем у цій проблемі. Редагувати: я уточнив мету правила, сподіваюся, що воно допомагає.
mellamokb

Коли ви говорите "випадкове число", ви маєте на увазі "випадкове ціле число" або "випадкове (усічене) дійсне число"? Можливо, є якась умовність, про яку я не знаю.
DavidC

@DavidCarraher: Дуже добре. Я мав на увазі випадкове ціле число, і я бачу, що це не ясно. Я оновлю питання. Редагувати: оновлено.
mellamokb

1
Чи дозволяється нам запитувати у рандомизатора скільки разів він генерував випадкові числа? Я був під враженням, що ми не можемо.
Метт

Відповіді:


2

J - 13 char

Це робить ті самі припущення, що і Гольфскрипт: що кількість кісток є в stdin, і ми перераховуємо рулони з кістки, які повинні вийти.

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

Пояснюється вибухом:

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

Якщо це якось незадовільно, ось довша 21-шарова програма, яку можна викликати, f''щоб генерувати випадкові числа, що містять стан і все.

r=:1+?  NB. free random function
c=:0
f=:3 :'r c=:1+c'

K аналоги: вільна випадкова функція r:{*1_draw x}, версія stdin (10 char) r'1+!. 0:` , версія функції (14 char), яку c:0;f:{r@c+:1}називають f[].
алгоритм

6

Пітон, 31 чол

Аналогічно скалеру, визначте генератор так:

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

Потім функція повертати рулони кістки:

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

Зателефонуйте D()будь-коли, коли вам потрібно рівномірний довільний рулон.


Ах, розумне використання eval, мені це подобається.
скалер

3

Scala 23

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

Метод r може бути (приблизно) реалізований так:

var cnt = 0 
val rnd = new util.Random 

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

приблизний тест:

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)

Кожен 6-й дзвінок повинен виробляти рівний розподіл по 6 значень, тому я викидаю 5.


2

GolfScript (15 символів)

Це передбачає, що кількість рулонів, необхідних, подається на stdin та перелічує багато результатів, які потрібно відключити.

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

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

Демонстрація в Інтернеті

Хоча я міг отримати бонус у 10 балів за використання менше 1000 рулонів для генерування 1000 чисел, це коштувало б мені набагато більше 10 символів. Тривіальний підхід вилучення відповідної ентропії, коли N кратний потужності 2 або 3, стає недостатньою, оскільки кількість доступних результатів mod 3 становить лише 333 + 111 + 37 + 12 + 4 + 1 = 498. Тому необхідно прийняти вибірку та відхилити підхід. Використовуючи такий підхід, ви можете отримати очікувані 2242 запиту від 1000 дзвінків r, але у бухгалтерії baseє додаткові накладні витрати і це дуже довга назва функції.


5
baseдуже довге ім'я функції" Ви, очевидно, не використовуєте Mathematica . Ми отримуємо такі чудеса , як NegativeBinomialDistribution, ExponentialGeneratingFunction, MathieuCharacteristicExponent, InverseFourierSequenceTransformі SemialgebraicComponentInstances. :-)
Mr.Wizard

1

Пітон 65 63

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

Функція R()- висхідний рандомізатор.

Використання:

$ ./rollDice.py
3
$ ./rollDice.py
5

Чому б не позбутися своєї forпетлі і просто зателефонувати Rодин раз перед whileциклом?
Кіт Рендалл

@KeithRandall Число, яке я повертаю, коли міняється кістка, - це остання цифра числа, яке повертає висхідний генератор. Мені потрібно здійснити 10 дзвінків до висхідного генератора, щоб забезпечити однакові ймовірності для всіх можливих цифр.
Метт

Чому 10 дзвінків? В принципі, якщо генератор випадковий, чи не повинен кожен виклик пропонувати однакову ймовірність для будь-якої з (десяти) цифр? Звичайно, на практиці ви можете розраховувати лише наближення до кожного числа.
DavidC

@DavidCarraher Генератор повертає випадкові числа від 1 до n, де n - кількість разів, яку ви викликали. Я переглядаю останню цифру цього повернутого числа. Якщо n не ціле число, кратне 10, ймовірність не буде однаковою. Наприклад: Якщо n = 13, ймовірності розбиваються так: 1/9 для рулонів 1,5,6 та 2/9 для рулонів 2,3,4
Метт

@Matt: Я припускав, що R()повертає поплавок, і ти захоплюєш найменш значущу цифру. Тепер, коли було з’ясовано, що R()повертає ціле число, це має сенс.
Кіт Рендалл

1

Пітона, 56

r визначається як:

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

генератор кісток d:

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

використання, наприклад, для 100 рулонів:

for i in range(100):print d()

ви можете, ймовірно, видалити, import mathякщо заміните math.ceil(...)наint(...)+1
Matt

Я б, але це дало б 7 як можливий вихід.
scleaver

О так. Я пропустив це.
Метт

mellamokb уточнив запитання, яке було у мене щодо висхідного рандомізатора. Вам заборонено просити про це н.
Метт

1

Mathematica 51

Генератор випадкових чисел, rскидається, встановивши глобальну змінну, nна 1.

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

Код

Не працює для найкоротшого коду ...

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

Використання

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

На 60000 рулонів кістки потрібно 60031 дзвінків h. Tallyпоказана розбивка за числами 1-6.

60031

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


1

Perl, 22 або 45

Реалізація висхідного генератора випадкових чисел:

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

Створення:

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

Тестування:

n число чіскар
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 рулонних кісток зайняли 60000042 дзвінків на r і 570,432735 секунд



0

GolfScript , 8 байт

f;3f*f(-

Спробуйте в Інтернеті!

Це один раз спливає генератор, а потім позбавляється від результату. Потім він котить f2 і помножує його на 3 (3 або 6), а потім віднімає f3-1 (0, 1, 2), що призводить до (3-2, 3-1, 3-0) або (6-2, 6-1, 6-0) W5.

Гольфскрипт та випадкова функція існували до того, як було поставлено це питання, тому це правове подання.

Це подання лише один раз. Якщо вам потрібно запустити його кілька разів за один дзвінок,

GolfScript , 12 байт

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

Спробуйте в Інтернеті!

Це скидає ваш дзвінок на 0, тож він скидається відповідно. Цей TIO показує 50 випадкових результатів.


0

C (gcc) , 31 байт

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

Кожні 6 дзвінків, ймовірність генерування кожного числа від 1 до 6 включно дорівнює.

cє #defined як виклик функції, яка генерує ідеальні випадкові числа.

Спробуйте в Інтернеті!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.