Risolve una funzione casuale interrotta


18

Un amico ha nel computer una scheda aggiuntiva che genera un numero perfettamente casuale compreso tra 1 e 5 inclusi. Sfortunatamente, hanno versato cola su di essa in qualche modo, e ora genera solo 2 per tutti i numeri da 1 a 4. Fortunatamente la casualità è preservata, ma 2 ha una probabilità dell'80% e 5 ha una probabilità del 20%, e non ci sono 1, 3 o 4 generati. Usando questa fonte casuale (chiamala BrokenRand()o qualcosa di simile), scrivi un generatore di numeri casuali funzionante che produca numeri da 1 a 5 ciascuno con una uguale probabilità del 20% con la stessa casualità perfetta della fonte originale.

Vince il programma più breve. Punti bonus assegnati per il numero minimo di chiamate in modo BrokenRandimparziale da parte di una consulenza focalizzata sul servizio clienti selezionata demograficamente, suddivisi per età e sesso - cioè io.

Risposte:


10

JavaScript - 69 caratteri

Questo utilizza l' estrattore von Neumann per generare bit imparziali; l'algoritmo generale è anche descritto sul sito Web di HotBits . Vengono utilizzati tre bit per formare un numero compreso tra 0 e 7. Tutti i numeri 5 e superiori vengono scartati e 1 viene aggiunto a ciascuno degli altri prima di essere stampato. Ho fatto una simulazione per dimostrare che questo non è fortemente distorto .

È necessario fornire la propria funzione r()per accedere all'RNG.

 for(;;v<5&&alert(v+1))for(v=i=0;i<3;a-b&&(v*=2,v+=a<b,i++))b=r(a=r())

Questo è davvero ben fatto! Mi piace come cortocircuitare il valore di incremento.
Snmcdonald,

Potresti generare 7 bit ed estrarre 3 numeri casuali per ridurre le chiamate a BrokenRand, ma probabilmente costerebbe qualche
colpo in

5

scala 79 caratteri:

// preparation: 
val r = util.Random 
def defektRNG = if (r.nextInt (5) == 0) 5 else 2 

(1 to 20).foreach (_ => print (" " + defektRNG))
// first impression:
// 2 2 2 2 2 2 2 5 2 2 5 2 2 2 5 2 2 2 2 2

def rnd : Int = { val k = (1 to 5).map (_ => defektRNG)
  if (k.sum == 13) k.findIndexOf (_ == 5) + 1 else rnd } 

// first impression:
(1 to 20).foreach (_ => print (" " + rnd))             
// 3 3 2 3 5 2 2 5 1 1 3 4 3 2 5 3 3 1 5 4
// control:
(1 to 50000).map (_ => rnd).groupBy (identity) .map (_._2.length) 
// scala.collection.immutable.Iterable[Int] = List(10151, 9997, 9971, 9955, 9926)

Ora per il vero golf, defektRNG alias brokenRand viene rinominato in b.

def r:Int={val k=(1 to 5).map(_=>b)
if(k.sum==13)k.findIndexOf(_==5)+1 else r} 

Come funziona: molto spesso, b restituisce una sequenza di 2 secondi. Ma se fai 5 chiamate a b, finirai molto spesso con un risultato di 4x2 e 1x5, è il secondo evento più probabile e può essere 5-2-2-2-2, 2-5-2-2 -2, 2-2-5-2-2, 2-2-2-5-2 e 2-2-2-2-5.

Questi hanno in comune che la somma è 4 * 2 + 5 = 13. L'indice dei primi cinque può essere utilizzato per definire un numero casuale valido. Se c'è più o meno di un 5, una somma maggiore o minore di 13, ripetere.

Un contatore in 'rnd' aka 'r' può mostrare quante chiamate sono necessarie in media per produrre i numeri. Vi sono 121 200 chiamate a r per 50.000 numeri casuali, il che non è impressionante. :)


3

> <> (Pesce) - 55 byte

Aggiornato per utilizzare lo stesso algoritmo di @user sconosciuto nella sua scala risposta

<? V = d + e: i & + &: i & + &: i & + &: i &: i
 0
 > 1 + $ 5 (vnao?;
 ^ <

Si aspetta che il generatore rotto sia collegato allo stdin; ecco lo script python che ho usato . Il codice corrisponde all'attuale specifica Fish, ma ho usato una versione modificata del vecchio interprete.

bash:$ for i in $(seq 1000); do ./bad_rand.py | ./myfish.py rand.fish; done >res.txt
bash:$ for i in $(seq 5); do echo -n "$i : "; grep -c $i res.txt; done
1 : 193
2 : 204
3 : 198
4 : 206
5 : 199

Farei un campione più grande ma è lento.


2

GolfScript, 23 byte

Risposta in ritardo, ma dal momento che questo è appena apparso in prima pagina ...

0{;[{r}5*].5?)\5-,4-}do

Utilizza lo stesso algoritmo della soluzione Scala dell'utente sconosciuto . Suppone che il generatore di numeri casuali distorto sia dato come una subroutine GolfScript denominata r; puoi definire tu stesso un RNG di parte adatto, ad es. come:

{5rand!3*2+}:r;

Ecco un breve test che dimostra la mancanza di parzialità. Sfortunatamente, il server GolfScript online è un po 'lento, quindi ho dovuto ridurre la dimostrazione a soli 100 campioni per completarla in tempo. Se l'esecuzione del test a livello locale con l' interprete GolfScript , provare ad aumentare la 100*per 1000*o addirittura 10000*.

(Anche il server GolfScript a volte si blocca e va in timeout in modo casuale. Se questo accade per te, riprovare di solito lo risolve. Succede anche con altro codice e succede solo sul server, non sul mio computer, quindi sono sicuro che è un problema con il server e non con il mio codice.)


-1

javascript, 160 caratteri senza ridurre la leggibilità aka ottimizzazione

function giveRandom(){
    var result = Math.floor(5 * Math.random()) + 1;
    while(BrockenRand() != 5){
        result = Math.floor(5 * Math.random()) + 1;
    }
    return result;
}

@ snmcdonald - alcuni di questi non sono un errore di battitura, è un modo per migliorare js random da un perfetto generatore casuale che approva solo (totalmente random!) il 20% dei risultati
www0z0k

Ti interessa spiegare cos'è BrockenBand(), allora?
Mateen Ulhaq,

6
Penso che ti sia sfuggito il punto
cthom06,

@muntoo - significatoBrockenRand
www0z0k

Salva alcuni byte in questo modo:function giveRandom(){return Math.ceil(Math.random()*5)}
user300375
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.