I am trying to test a program which checks for correct use of brackets. To do this I want to generate Long strings of numbers with correct use of brackets (to test incorrect uses I can easily just swap around individual characters or groups of characters)
I can easily generate a vector of non-bracket characters. However, To place brackets correctly I need n
unique indices. I do not know of a way to efficiently generate random indices (a list of unique random numbers in a range) so I would like either a way to do that or a way of converting random numbers into unique indices.
The two best approaches I can think of for this are:
0-N
, shuffle it and then take the first n
n
members then convert it to a vectorThe first approach is efficient for N = n + $\epsilon$
but very inefficient for N >> n
while the second approach is very inefficient for N = n + $\epsilon$
but efficient for N >> n
.
Note:
n
is the number of brackets N
is the number of characters$\epsilon$
is some small
positive numberWell you already answered your own question :^)
I would go with No 1. While epsilon analysis is nice, in the real world, there's a lot more going on. Random accesses on vectors are very, very fast, while the hashing and regenerating random numbers is probably slow (though as always do benchmarks).
However if you're not generating a LOT of brackets, the performance difference is probably negligible.
For your first solution you can use the rand
crate and its SliceRandom
trait. Do something like:
use rand::seq::SliceRandom;
fn whatever() {
let mut numbers: Vec<usize> = (0..N).iter().copied().collect();
numbers.shuffle(&mut rand::thread_rng());
let usable_numbers = numbers[0..n];
// Tada
}
The other solution
fn whatever() {
let mut out_map = HashSet::new();
while out_map.len() < n {
out_map.insert(rand::thread_rng().gen::<usize>() % N);
}
let numbers = out_map.into_iter().collect::<Vec<_>>();
}