Учитывая справедливую монету в качестве входных данных, генерировать любой конкретный несправедливый результат


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.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.5303 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,52666. }

0.529798

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

гистограмма

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

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

.10000111101011100001010001111010111000010100011110110

Исходя из слева направо, по одной цифре за раз:

Если RandomInteger [] возвращает 1, тогда answer = 1,

Иначе, если second RandomInteger [] возвращает 0, тогда answer = 0,

Иначе, если третий RandomInteger [] возвращает 0, ответ = 0,

Else ....

Если после проверки всех цифр ответа по-прежнему нет, то answer = 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

Wolfram Language (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.

Чтобы сделать его короче, мы начнем со случайного монетного клипа, который в любом случае возвращается половину времени. Если coinflip не соответствует случаю, когда мы должны его вернуть, замените его результатом повторения по 2pмодулю 1. (То есть, когда pменьше 1/2, замените 1; когда pбольше 1/2 , заменить 0. Это эквивалентно замене ⌈1-2p⌉.)

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