DeejUK
DeejUK

Reputation: 13481

Get a non-prime number and its factors below a given maximum

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

Answers (2)

Tunaki
Tunaki

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

Henry
Henry

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

Related Questions