Ho una lunga lista di elementi che voglio ripetere in ordine casuale. Tuttavia, non posso modificare l'elenco e non voglio nemmeno crearne una copia, perché 1) è grande e 2) ci si può aspettare che l'iterazione venga cancellata anticipatamente.Algoritmi Lazy Shuffle
List<T> data = ...;
Iterator<T> shuffled = shuffle(data);
while (shuffled.hasNext()) {
T t = shuffled.next();
if (System.console().readLine("Do you want %s?", t).startsWith("y")) {
return t;
}
}
System.out.println("That's all");
return t;
Sto cercando un algoritmo erano il codice di cui sopra verrebbe eseguito nel O(n)
(e preferibilmente richiedono solo O(log n)
spazio), in modo caching gli elementi che sono stati prodotti in precedenza non è un'opzione. Non mi interessa se l'algoritmo è distorto (a patto che non sia ovvio).
(I utilizza pseudo-Java nella mia interrogazione, ma è possibile utilizzare altre lingue, se lo si desidera)
Qui è la migliore che ho avuto finora.
Iterator<T> shuffle(final List<T> data) {
int p = data.size();
while ((data.size() % p) == 0) p = randomPrime();
return new Iterator<T>() {
final int prime = p;
int n = 0, i = 0;
public boolean hasNext() { return i < data.size(); }
public T next() {
i++; n += prime;
return data.get(n);
}
}
}
Iterando tutti gli elementi O(n)
, spazio costante, ma ovviamente polarizzati in quanto può produrre solo data.size()
permutazioni.
Forse questo potrebbe darvi un suggerimento: http: // StackOverflow.it/questions/352203/generation-permutations-lazily – dsd
La risposta sembra essere un algoritmo Steinhaus-Johnson-Trotter, che genera tutte le permutazioni in modo iterativo. Sto cercando una permutazione singola (scelta a caso), costruita in modo iterativo. – Cephalopod
Una risposta a una domanda simile su questo sito ha suggerito di utilizzare un algoritmo di crittografia con dimensioni di blocco variabili per crittografare la sequenza 0, 1, 2, ... http://stackoverflow.com/a/18185810/154770 –