2012-03-23 11 views

risposta

5

Qualcosa di simile a questo:

int count = 0; 
int index = -1; 
for (int i = 0; i != n; ++i) 
{ 
    if (values[i]) 
    { 
     ++count; 
     if (unit_random <= 1.0f/count) 
     { 
      index = i; 
     } 
    } 
} 

Così per 4 valori per esempio, si ottengono i seguenti probabilità per i loro indici:

1: (1/1) * (1/2) * (2/3) * (3/4) = 1/4 
2: (1/2) * (2/3) * (3/4) = 1/4 
3: (1/3) * (3/4) = 1/4 
4: 1/4 = 1/4 

EDIT: Come Steve Jessop ha sottolineato il punto di confronto floating alla fine porterà a una selezione molto non uniforme. Supponendo unit_random è definito come rand()/RAND_MAX il confronto può essere cambiato in:

typedef unsigned long long u64; 
u64 product = u64(count) * rand(); 
if (product <= u64(RAND_MAX)) 

Questo non darà perfetta distribuzione a causa della natura discreta rand ma sarà meglio.

+0

Scusa, ho dimenticato una parola. Volevo dire: restituire l'indice di un valore VERO casuale ... Non solo il primo che troviamo. Ma la funzione dovrebbe restituire a caso uno qualsiasi degli indici contenenti un VERO. – PaulV

+0

@PaulV Questo è esattamente ciò che fa questa funzione. –

+0

@Nick Sì, ma ho modificato la mia risposta;) –

0

Non è del tutto chiaro cosa significhi "randomly distibuted". Significa "con qualche distribuzione sconosciuta"? Se è così, facciamo finta che tutte le possibili distribuzioni siano ugualmente probabili, quindi la "distribuzione attesa" (come in "valore atteso") è uniforme (la "media" di tutte le possibili distribuzioni). Quindi qualsiasi indice è VERO con una probabilità di 1/2. Quindi il tuo compito diventa il compito di iterare attraverso l'array il più rapidamente possibile. Inizia dall'inizio, come se fosse normale iterare un array, finché non si incontra un valore TRUE.

+0

Intendo dire che non esiste un modello per i valori. Non seguono alcun tipo di funzione di distribuzione. – PaulV

+1

Indovina che significa [distribuzione uniforme] (http://en.wikipedia.org/wiki/Uniform_distribution_ (discreto)), giusto? ;) –

+0

@PaulV: "randomly distributed" è probabilmente una brutta frase da usare se intendete "non seguono alcun tipo di funzione di distribuzione". Avresti potuto dire "valori arbitrari booleani" o semplicemente "valori booleani". Quindi dovresti definire cosa intendi per "più veloce", perché se non hai una distribuzione per i valori allora non esiste nulla come "runtime previsto" per qualsiasi algoritmo la cui velocità dipende dai valori. –

0

Per restituirlo, è necessario prima contare i valori True (non c'è modo di saltarlo) e accumulare i loro indici in un altro array. E dopo aver contato devi solo generare un numero intero casuale da 0 a N-1 (dove N è il numero di valori True) e scegliere il valore dall'array creato.

in pseudo-python:

indices=[] 

for i,val in enumerate(arr): 
    if val: 
     indices.append(i) 
randi = randint(0,len(indices)-1) 
return indices[randi] 
1

La soluzione più veloce - a patto che non si seleziona più volte sullo stesso array - è quello di scegliere un indice a caso, restituirlo se è vero, e ripetere se non. Nel migliore dei casi, dove tutte le voci sono vere, questo è O (1); nel peggiore dei casi, dove una sola voce è vera, questa è O (n) (ogni tentativo ha una probabilità di 1/n di colpire l'unico valore vero, il che significa un numero atteso di tentativi di n). Questo non è peggio di nessuna delle altre soluzioni pubblicate.

Se si prevede che la matrice di solito sia quasi completamente falsa, tuttavia, è possibile scegliere un'altra soluzione, poiché la varianza in fase di esecuzione di questo metodo casuale sarà elevata.

+1

"Non è peggio di nessuna delle altre soluzioni pubblicate" - la complessità non lo è, ma utilizza la cache in modo meno efficiente della risposta di Andreas. E FWIW, il codice di Andreas cattura il caso di fallimento, e questo approccio non lo fa. Forse la cosa "migliore" (scambiare il caso previsto vs il caso peggiore) è eseguire un piccolo numero di campioni casuali, e se nessuno di loro trova un valore vero, allora concludi che l'array è scarso e ricadi alla soluzione di Andreas o simili . –

0

Soluzione semplice: Genera una permutazione di possibili indici (1: n) e nell'ordine di tale indice di ritorno permutazione se il valore corrispondente è vero

def randomTrue(x): 
    perm = randomPermute(0:len(x)) 
    for i in perm: 
     if x[i]: 
      return i 
Problemi correlati