З огляду на справедливу монету як внесок, генеруйте будь-який конкретний несправедливий результат


13

Зробити справедливу монету легко, використовуючи несправедливу монету, але реверс важче здійснити.

Ваша програма отримає одне число X (від 0 до 1 включно) як вхід. Введення не повинно просто бути жорстко закодованим як число посередині вихідного коду. Потім він повинен повернути одну цифру: a 1з ймовірністю X та 0іншим чином.

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

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

Це кодовий гольф, найкоротша відповідь виграє.


Яку форму приймає вхід? Якщо ми гарантуємо, що це номер плаваючої точки IEEE-754 заданого розміру, то це насправді досить просто.
Пітер Тейлор

Відповіді:


4

Perl, 37 42 char

($d/=2)+=rand>.5for%!;print$d/2<pop|0

Приймає довільну ймовірність як аргумент командного рядка. Побудовує рівномірне випадкове число в $dі порівнює його з вхідним.

Раніше 52 чарівне рішення

$p=<>;do{$p*=2;$p-=($-=$p)}while$--(.5<rand);print$-

1
Мені вражено, що ви повернулися через 6 років, щоб оптимізувати це рішення.
Міша Лавров

3

Пітон, 81 ч

import random
print(sum(random.randint(0,1)*2**-i for i in range(9))<input()*2)+0

Можна вимкнути трохи, але ніколи не більше 1%.


На мене виглядає набагато краще, ніж на 1%. Я запустив вашу програму 100 000 разів для ймовірностей [0,1] з кроком 0,01 і порівняв це з random.random() < desiredProbabilityвикористанням цього сценарію: gist.github.com/3656877 Вони ідеально відповідають i.imgur.com/Hr8uE.png
Метт-

Хоча, як і очікувалося, random.random() < xзначно швидше.
Метт

3

Mathematica 165

Не впорядкований, але деякі можуть знайти алгоритм, що цікавить:

d = RealDigits; r = RandomInteger;
f@n_ := If[(c = Cases[Transpose@{a = Join[ConstantArray[0, Abs[d[n, 2][[2]]]], d[n, 2][[1]]], 
         RandomInteger[1, {Length@a}]}, {x_, x_}]) == {}, r, c[[1, 1]]]

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

f[.53]

1

Перевірити

Давайте подивимось, чи f[.53]справді виробляє цінність 1приблизно 53% часу. Кожен тест обчислює% для зразків 10 ^ 4.

Проведено та усереднено 50 таких тестів.

Table[Count[Table[f[.53], {10^4}], 1]/10^4 // N, {50}]
Mean[%]

{0,5292, 0,5256, 0,5307, 0,5266, 0,5245, 0,5212, 0,5316, 0,5345, 0,5297, 0,5334, 0,5306, 0,5288, 0,528, 0,5379, 0,5293, 0,5263, 0,539, 0,5322, 0,5195, 0,5208, 0,5382, 0,543, 0,5336, 0,5305, 0,5305 , 0,5297, 0,5318, 0,5243, 0,5281, 0,5361, 0,5349, 0,5308, 0,5265, 0,5309, 0,5233, 0,5345, 0,5316, 0,5376, 0,5264, 0,5269, 0,5295, 0,523, 0,5294, 0,5326, 0,5316, 0,5334, 0,5165, 0,5296, 0,5266, 0,5266 }

0,529798

Гістограма результатів

гістограма

Пояснення (сповіщення спойлера!)

Базове представлення .53 становить

.10000111101011100001010001111010111000010100011110110

Зліва направо, одна цифра за раз:

Якщо RandomInteger [] повертає 1, то відповідь = 1,

Якщо інший RandomInteger [] поверне 0, то відповідь = 0,

В іншому випадку, якщо третій RandomInteger [] поверне 0, відповідь = 0,

Ще ...

Якщо після перевірки всіх цифр все ще немає відповіді, відповідь = RandomInteger [].


1

Haskell, 107 символів:

import System.Random
g p|p>1=print 1|p<0=print 0|1>0=randomIO>>=g.(p*2-).f
f x|x=1|1>0=0.0
main=readLn>>=g

0

Мова Вольфрама (Mathematica) , 42 байти

RandomInteger[]/.⌈1-2#⌉:>#0@Mod[2#,1]&

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

Це рекурсивний підхід. Неробочий, алгоритм:

  • Якщо ймовірність введення pменше 1/2, тоді, коли монета перевернеться 0, поверніть 0. Інакше повторіть роботу 2p; якщо припустити правильність, загальна ймовірність отримати 1 - це половина 2pабо p.
  • Якщо ймовірність введення pбільша за 1/2, тоді, коли монета перевернеться 1, поверніть 1. В іншому випадку повторіть роботу 2p-1; якщо припустити правильність, загальна ймовірність отримати 0 - це половина 1-(2p-1)або 1-p.

Щоб зробити його коротшим, ми починаємо з випадкового монети, який в будь-якій гілці повертається вдвічі. Якщо монета не відповідає випадку, коли ми повинні повернути її, замініть її результатом повторення на 2pмодуль 1. (Тобто, коли pменше 1/2, замініть 1; коли pбільше 1/2 , замініть 0. Це еквівалентно заміні ⌈1-2p⌉.)

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