Data una moneta equa come input, genera un risultato iniquo particolare


13

È facile generare una moneta giusta usando una moneta ingiusta, ma il contrario è più difficile da realizzare.

Il tuo programma riceverà un numero X (tra 0 e 1, incluso) come input. L'input non deve essere semplicemente codificato come un numero nel mezzo del codice sorgente. Deve quindi restituire una singola cifra: a 1con una probabilità di X e a 0altrimenti.

Il tuo programma è autorizzato a utilizzare solo una forma di generatore di numeri casuali nel codice sorgente: int(rand(2))(o un equivalente), che restituisce uno zero o uno con uguale probabilità. Puoi includere o accedere a questa funzione tutte le volte che vuoi nel tuo codice. Devi anche fornire tu stesso la funzione come parte del codice.

Al tuo programma non è consentito utilizzare altre funzioni di generazione di numeri casuali o fonti esterne (come le funzioni di ora e data) che potrebbero funzionare come una funzione di generazione di numeri casuali. Inoltre, non può accedere a nessun file esterno o passare il lavoro a programmi esterni.

Questo è il codice golf, vince la risposta più breve.


Quale forma prende l'input? Se abbiamo la garanzia che si tratta di un numero in virgola mobile IEEE-754 di una determinata dimensione, allora in realtà è abbastanza semplice.
Peter Taylor,

Risposte:


4

Perl, 37 42 char

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

Prende la probabilità arbitraria come argomento della riga di comando. Crea un numero casuale uniforme $de lo confronta con l'input.

In precedenza, soluzione 52 caratteri

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

1
Sono impressionato dal fatto che sei tornato 6 anni dopo per ottimizzare questa soluzione.
Misha Lavrov,

3

Python, 81 caratteri

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

Può essere spento un po ', ma mai più dell'1%.


Mi sembra molto meglio dell'1%. Ho eseguito il tuo programma 100.000 volte per probabilità di [0,1] con un passo di 0,01 e ho confrontato questo con l' random.random() < desiredProbabilityuso di questo script: gist.github.com/3656877 Si abbinano perfettamente i.imgur.com/Hr8uE.png
Matt

Sebbene, come previsto, random.random() < xè notevolmente più veloce.
Matt,

3

Mathematica 165

Non semplificato, ma alcuni potrebbero trovare l'algoritmo di interesse:

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

uso

f[.53]

1

Dai un'occhiata

Vediamo se f[.53]produce davvero il valore 1circa il 53% delle volte. Ogni test calcola la% per campioni di 10 ^ 4.

50 di questi test vengono eseguiti e mediati.

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,566 }

0.529798

Istogramma dei risultati

istogramma

Spiegazione (avviso spoiler!)

La rappresentazione di base 2 di .53 è

.10000111101011100001010001111010111000010100011110110

Procedendo da sinistra a destra, una cifra alla volta:

Se RandomInteger [] restituisce 1, quindi rispondi = 1,

Altrimenti se il secondo RandomInteger [] restituisce 0, quindi rispondi = 0,

Altrimenti se il terzo RandomInteger [] restituisce 0, la risposta = 0,

Altro....

Se, quando tutte le cifre sono state testate, non c'è ancora risposta, allora answer = RandomInteger [].


1

Haskell, 107 caratteri:

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 byte

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

Provalo online!

Questo è un approccio ricorsivo. Ungolfed, l'algoritmo è:

  • Se la probabilità di input pè inferiore a 1/2, quindi quando il coinflip sale 0, restituisce 0. Altrimenti, ricomincia 2p; supponendo la correttezza, la probabilità complessiva di ottenere 1 è la metà di 2po p.
  • Se la probabilità di input pè maggiore di 1/2, quindi quando il coinflip sale 1, ritorna 1. Altrimenti, ricomincia 2p-1; assumendo la correttezza, la probabilità complessiva di ottenere 0 è la metà di 1-(2p-1)o 1-p.

Per renderlo più breve, iniziamo con il coinflip casuale, che, in entrambi i rami, viene restituito metà del tempo. Se il coinflip non corrisponde al caso in cui dovremmo restituirlo, sostituirlo con il risultato della ripetizione sul 2pmodulo 1. (Cioè, quando pè inferiore a 1/2, sostituire 1; quando pè maggiore di 1/2 , sostituire 0. Ciò equivale a sostituire ⌈1-2p⌉.)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.