Un sistema random con % statistiche

13 views
Skip to first unread message

RedFoxy

unread,
Oct 20, 2013, 7:31:16 PM10/20/13
to zb-p...@googlegroups.com
ciao a tutti,
volevo sapere se esiste un sistema randomico che però mi permetta di rispettare la statistica di uscita, in pratica se faccio un random da 1 a 10 aspettando che esca il numero 7, devo fare al massimo 10 tentativi perché il 7 esca, a differenza del rnd di php che può variare dal esce subito a non esce se non dopo infiniti tentativi.
Fino adesso ho usato memcache con un sistema random creato da me, ma sto' avendo problemi con memcache che crasha senza motivi apparenti, quindi cercavo qualcosa magari di esistente e valido sostituto…

Idee?

Cristiano Verondini

unread,
Oct 20, 2013, 8:39:19 PM10/20/13
to zb-p...@googlegroups.com

On 21/ott/2013, at 01.31, RedFoxy wrote:

volevo sapere se esiste un sistema randomico che però mi permetta di rispettare la statistica di uscita, in pratica se faccio un random da 1 a 10 aspettando che esca il numero 7, devo fare al massimo 10 tentativi perché il 7 esca, a differenza del rnd di php che può variare dal esce subito a non esce se non dopo infiniti tentativi.

Questa non è statistica, la statistica non permette di fare previsioni, e le funzioni di php (in particolare mt_rand() che è meglio di rand()) forniscono una distrubuzione uniforme, nel senso statistico del termine, dei valori 'estratti'.

La soluzione che rispecchia quello che ti aspetti, è invece la seguente:

(1) generi un array di n elementi che vengono 'mischiati' tramite una funzione pseudocasuale.

(2) ogni volta che hai bisogno di un nuovo valore, lo estrai dall'array (shift o pop, non è importante).

(3) quando l'array ha raggiunto lunghezza zero, lo rigeneri.

Questa una possibile (semplice) soluzione:

class randomPool {

protected $min, $max, $dt = array();

function __construct($min, $max) {

$this->min = $min;
$this->max = $max;
}

function get() {

if (count($this->dt) === 0)
$this->generate();

return array_pop($this->dt);
}

protected function generate() {

// genera un array contenente i valori da $min a $max inclusi
// e poi li 'mischia'

$this->dt = range($this->min, $this->max);
shuffle($this->dt);
}
}

// esempio di uso
$r = new randomPool(1, 10);

for ($i = 0; $i < 100; $i++) echo $r->get() . ' ';

Naturalmente se hai la necessità che il tutto funzioni fra diverse pagine erogate da un web server hai bisogno di definire la persistenza della struttura:

(1) eg. in sessione nel caso il pool sia a disposizione di uno stesso utente
(2) eg. su db nel caso debba essere condiviso fra più utenti (in questo caso puoi usare strategie differenti che generano direttamente record con le caratteristiche che ti interessano in una tabella).

-- 
Cristiano Verondini






RedFoxy

unread,
Oct 21, 2013, 9:10:26 AM10/21/13
to zb-p...@googlegroups.com

Il giorno 21/ott/2013, alle ore 02:39, Cristiano Verondini <cris...@verondini.it> ha scritto:

(1) eg. in sessione nel caso il pool sia a disposizione di uno stesso utente
(2) eg. su db nel caso debba essere condiviso fra più utenti (in questo caso puoi usare strategie differenti che generano direttamente record con le caratteristiche che ti interessano in una tabella).

Infatti fino adesso mettevo l'array in memcache e ora pensavo di metterlo in un db mysql magari con tabella di tipologia MEMORY sia per non gravare sul HD sia per aver tempi rapidi di risposta.

Attualmente il mio codice per il random con memcahce è:

function memRand($memID, $min, $max)
{
$a = inMemCache::get('memRand_' . $memID); // Prendi l'array
if (!is_array($a) || count($a)==0) for($y=$min; $y<=$max; $y++) $a[$y]=$y; // Riempi l'array se vuoto
$b = array_rand($a); // Prendi una posizione a caso dell'array
$c = $a[$b]; // Prendi il valore corrispondente
unset($a[$b]); // Cancelli la posizione in quanto già uscita
$x = inMemCache::set('memRand_' . $memID, $a, MEMCACHE_COMPRESSED); // Aggiorniamo l'array in memcache
return $c; // Restituisci il valore uscito
}

Reply all
Reply to author
Forward
0 new messages