2013-02-18 2 views
6

Voglio generare numeri casuali, ma non voglio che siano dall'array excludeRows. Ecco il mio codice.Genera numeri casuali ad eccezione di determinati valori

public int generateRandom(int start, int end, ArrayList<Integer> excludeRows) { 
    Random rand = new Random(); 
    int range = end - start +1 - excludeRows.size(); 
    int random = rand.nextInt(range) + 1; 

    for(int i = 0; i < exclude.size(); i++) { 
     if(excludeRows.get(i) > random) { 
      return random; 
     } 
     random++; 
    } 

    return random; 
} 

utilizzo questa funzione in un ciclo while, e durante ogni iterazione aggiungo un nuovo valore per excludeRows. A volte restituisce numeri che appartengono a excludeRows. Qual è il problema?

+2

Sono 'excludeRows' e' exclude' la stessa cosa? – Vlad

+0

sì, ho dimenticato di cambiare il nome – user2081119

+0

In questa funzione non si aggiungono numeri a 'excludeRows'. Quindi nella mia soluzione non lo faccio neanche io. Dovrei integrarlo? – qben

risposta

5
if(!exclude.contains(random)) 
    return random; 

provare questo ogni volta lo farà restituire il valore che non è in esclusione.

+1

funziona! Molte grazie! :) – user2081119

+0

@ user2081119 Puoi upvotare e accettare. Grazie –

+0

@ user2081119 Ti suggerisco di dare un'occhiata alla mia soluzione. Ci sono alcune osservazioni che sarebbero utili, penso. – qben

2

di controllare:

for(int i = 0; i < exclude.size(); i++) { 
    if(exclude.get(i) > random) { 
     return random; 
    } 

e se solo il primo è più grande, si tornerà il valore. Sei sicuro che exclude è ordinato?

È possibile utilizzare if(exclude.contains(random)) o il seguente algoritmo:

se (end-start) è un numero ragionevole, ed è necessario quasi tutti i valori che è possibile creare un elenco di tutti i numeri accettabili e utilizzare casuale in questa dimensione dell'elenco e scegliere la casuale valore come indice. quindi rimuovere il numero indesiderato dall'elenco e ottenere un altro indice casuale.

+2

Credo che si basi sul fatto che l'esclusione è ordinata. –

6

Penso che ci siano alcuni errori.

1) L'intervallo deve essere end-start + 1, perché questo è l'intervallo desiderato.
2) Se si desidera veramente numeri casuali (come "casuali" nei computer), non si dovrebbe semplicemente ottenere il prossimo numero disponibile. Perché in questo caso il tuo numero casuale avrà le caratteristiche dei numeri esclusi densità/frequenza.

public int generateRandom(int start, int end, ArrayList<Integer> excludeRows) { 
    Random rand = new Random(); 
    int range = end - start + 1; 
    int random; 

    boolean success = false; 
    while(!success) { 
     random = rand.nextInt(range) + 1; 
     for(Integer i: excludeRows) { 
      if(i == random) { 
       break; 
      } else if (i > random) { 
       success = true; 
       break; 
      } 
     } 
    } 
    return random; 
} 

UPDATE

Con la risposta di Achintya Jha mio codice potrebbe essere migliorata (ma nota ci sono alcune osservazioni pure):

public int generateRandom(int start, int end, ArrayList<Integer> excludeRows) { 
    Random rand = new Random(); 
    int range = end - start + 1; 

    int random = rand.nextInt(range) + 1; 
    while(excludeRows.contains(random)) { 
     random = rand.nextInt(range) + 1; 
    } 

    return random; 
} 
+1

Grazie mille! bella soluzione – user2081119

0

In realtà, non è necessario utilizzare contains(random) con un ciclo while.

Per semplificare la domanda, vediamo cosa succede se abbiamo solo un valore escluso. Possiamo dividere il risultato in parti 2. Quindi il numero di valori possibili è range-1. Se il numero casuale è inferiore al valore escluso, basta restituirlo. Altrimenti, potremmo aggiungere 1.

Per più valori esclusi, Possiamo dividere il set di risultati nelle parti size+1, dove size indica il numero di valori esclusi. Quindi il numero di valori possibili è range-size. Quindi ordiniamo i valori esclusi in ordine crescente. Se il numero casuale è inferiore al valore escluso meno i, restituire semplicemente il numero casuale i, dove i è l'indice del valore escluso.

public int generateRandomNumberWithExcepts(int start, int end, List<Integer> excepts) { 
    int size = excepts.size(); 
    int range = end - start + 1 - size; 
    int randNum = random.nextInt(range) + start; 
    excepts.sort(null); // sort excluding values in ascending order 
    int i=0; 
    for(int except : excepts) { 
     if(randNum < except-i){ 
      return randNum + i; 
     } 
     i++; 
    } 
    return randNum + i; 
}