Reputation: 13481
I need to randomly pick a non-prime number below a given maximum, and return all its factors.
I already have all the non-primes and their factors stored in a Map<Integer, Integer[]>
that is calculated once on startup.
Here's an idea of the implementation:
public Pair<Integer, Integer[]> getNonPrimeAndFactors(int maximum)
{
//Randomly select a non-prime less than maximum
return new Pair<Integer, Integer[]>(nonPrime, factors.get(nonPrime));
}
I'm not really sure what data structure to use in order to pick a key in that Map
randomly whilst still being less than maximum
. Picking a random number less than maximum, then iterating down calling factors.hasKey(randomNumber--)
would be a bit crap.
I'm using Java 7 and Guava, so have Google's collections to pick from.
Upvotes: 0
Views: 167
Reputation: 137104
You can get a random key less than the maximum by converting the key set to a SortedSet
and keep the head set below the maximum value.
When you have such a set, it is then possible to convert it to a list and get a random element by index:
public Pair<Integer, Integer[]> getNonPrimeAndFactors(int maximum) {
SortedSet<Integer> set = new TreeSet<>(factors.keySet()).headSet(maximum);
List<Integer> keys = new ArrayList<>(set);
Integer nonPrime = keys.get(ThreadLocalRandom.current().nextInt(keys.size()));
return new Pair<Integer, Integer[]>(nonPrime, factors.get(nonPrime));
}
Upvotes: 2
Reputation: 43738
generate a random number below max, check if it is a non-prime by looking into the table. If it is a prime restart from the beginning, i.e. generate a new random number.
Since the non-primes are much more frequent than the primes this procedure will not take long.
Upvotes: 1