Étant donné une pièce de monnaie équitable en entrée, générer un résultat injuste

13

Il est facile de générer une pièce juste à l'aide d'une pièce injuste, mais l'inverse est plus difficile à réaliser.

Votre programme recevra un numéro X (entre 0 et 1, inclus) en entrée. L'entrée ne doit pas simplement être codée en dur sous forme de nombre au milieu du code source. Il doit alors renvoyer un seul chiffre: a 1avec une probabilité de X et a 0sinon.

Votre programme n'est autorisé à utiliser qu'une seule forme de générateur de nombres aléatoires dans le code source: int(rand(2))(ou un équivalent), qui renvoie un zéro ou un avec une probabilité égale. Vous pouvez inclure ou accéder à cette fonction autant de fois que vous le souhaitez dans votre code. Vous devez également fournir la fonction vous-même dans le cadre du code.

Votre programme n'est pas autorisé à utiliser d'autres fonctions de génération de nombres aléatoires ou des sources externes (telles que les fonctions d'heure et de date) qui pourraient fonctionner comme une fonction de génération de nombres aléatoires. Il ne peut pas non plus accéder à des fichiers externes ni transmettre le travail à des programmes externes.

C'est le golf de code, la réponse la plus courte l'emporte.

PhiNotPi
la source
Quelle forme prend l'entrée? Si nous avons la garantie qu'il s'agit d'un nombre à virgule flottante IEEE-754 d'une taille donnée, cela est en fait assez simple.
Peter Taylor

Réponses:

4

Perl, 37 42 car.

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

Prend une probabilité arbitraire comme argument de ligne de commande. Construit un nombre aléatoire uniforme dans $det le compare à l'entrée.

Plus tôt, solution de 52 caractères

$p=<>;do{$p*=2;$p-=($-=$p)}while$--(.5<rand);print$-
foule
la source
1
Je suis impressionné que vous soyez revenu 6 ans plus tard pour optimiser cette solution.
Misha Lavrov
3

Python, 81 caractères

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

Peut être légèrement décalé, mais jamais supérieur à 1%.

Keith Randall
la source
Ça me semble beaucoup mieux que 1%. J'ai exécuté votre programme 100 000 fois pour des probabilités de [0,1] avec un pas de 0,01 et je l'ai comparé à l' random.random() < desiredProbabilityaide de ce script: gist.github.com/3656877 Ils correspondent parfaitement i.imgur.com/Hr8uE.png
Matt
Bien que, comme prévu, random.random() < xest considérablement plus rapide.
Matt
3

Mathematica 165

Pas rationalisé, mais certains peuvent trouver l'algorithme d'intérêt:

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]]]

Usage

f[.53]

1

Vérifier

Voyons si f[.53]cela produit vraiment la valeur 1environ 53% du temps. Chaque test calcule le% pour des échantillons de 10 ^ 4.

50 tests de ce type sont exécutés et moyennés.

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,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,5266, 0,5266 }

0,529798

Histogramme des résultats

histogramme

Explication (alerte spoiler!)

La représentation en base 2 de 0,53 est

.10000111101011100001010001111010111000010100011110110

De gauche à droite, un chiffre à la fois:

Si RandomInteger [] renvoie 1, alors réponse = 1,

Sinon Si le deuxième RandomInteger [] renvoie 0, alors réponse = 0,

Sinon Si le troisième RandomInteger [] renvoie 0, la réponse = 0,

Autre....

Si, lorsque tous les chiffres ont été testés, il n'y a toujours pas de réponse, alors answer = RandomInteger [].

DavidC
la source
1

Haskell, 107 caractères:

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
Rotsor
la source
0

Wolfram Language (Mathematica) , 42 octets

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

Essayez-le en ligne!

Il s'agit d'une approche récursive. Non golfé, l'algorithme est:

  • Si la probabilité d'entrée pest inférieure à 1/2, alors lorsque le coinflip arrive à 0, retournez 0. Sinon, répétez 2p; en supposant l'exactitude, la probabilité globale d'obtenir 1 est la moitié de 2pou p.
  • Si la probabilité d'entrée pest supérieure à 1/2, alors lorsque le coinflip arrive à 1, retournez 1. Sinon, répétez 2p-1; en supposant l'exactitude, la probabilité globale d'obtenir 0 est la moitié de 1-(2p-1)ou 1-p.

Pour le raccourcir, nous commençons par le coinflip aléatoire, qui, dans l'une ou l'autre branche, est retourné la moitié du temps. Si le coinflip ne correspond pas au cas où nous sommes censés le retourner, remplacez-le par le résultat de la récurrence sur 2pmodulo 1. (C'est-à-dire, quand pest inférieur à 1/2, remplacez 1; quand pest supérieur à 1/2 , remplacez 0. Cela équivaut à remplacer ⌈1-2p⌉.)

Misha Lavrov
la source