Generate 10 non-duplicate random integers from 0 to 20 [duplicate] - java

This question already has answers here:
Creating random numbers with no duplicates
(20 answers)
Generating 10 random numbers without duplicate with fundamental techniques
(10 answers)
How to generate random numbers from 0 to 100 without duplicates when user enters the size of the array in Java?
(5 answers)
Closed last month.
I have a problem in generating the non-duplicate numbers. I tried to do the do-while loop but it seems not working. How do I fix it?
import java.util.Arrays;
public class Assignment2_Q2 {
public static void main (String[] args){
int[] myList = new int[10];
number(myList);
sortedOrder(myList);
display (myList);
}
public static void number(int[] list){
int random;
random = (int)(Math.random() * 21);
list[0] = random;
for (int i = 1; i < list.length; i++){
do{
random = (int)(Math.random() * 21);
list[i] = random;
}while(list[i] == list[i-1]);
}
}
public static void sortedOrder(int[] list){
java.util.Arrays.sort(list);
}
public static void display(int[] list){
System.out.println("The array in the sorted order:\n" + Arrays.toString(list) + "\n");
}
}
Example output:
The array in the sorted order:
[0, 0, 6, 7, 13, 16, 16, 18, 19, 20]
As you can see, 0 and 16 come twice each. They are duplicates. I have also seen a number coming three times in one run.

Generate a list of numbers 1-20, then shuffle the list, then take the first 10.
List<Integer> nums = IntStream.rangeClosed(1, 20).boxed().collect(toList());
Collections.shuffle(nums);
nums = nums.subList(0, 10);

Your problem is in while(list[i] == list[i-1]) This isn't checking that the list doesn't contain the random number you generated. It's checking that the last 2 generated numbers aren't the same You're not checking that the previous numbers didn't match. The right way to do this is:
for (int i = 0; i < list.length; i++){
bool found = false;
do{
random = (int)(Math.random() * 21);
for(int j=0; j<i; j++) {
if(list[j] == random) {
found = true;
}
}
}while(found = false);
list[i] = random;
}

public static void main(String[] args) {
int[] myList = new int[10];
number(myList);
}
public static void number(int[] list) {
int random;
Set<Integer> used = new HashSet<>();
for (int i = 0; i < list.length; i++) {
do {
random = (int) (Math.random() * 21);
} while (used.contains(random)); // check if the number has been used before
list[i] = random;
used.add(random);
}
}

Related

How to build a random integer array of distinct elements? [duplicate]

This question already has answers here:
Generating Unique Random Numbers in Java
(21 answers)
Closed 1 year ago.
I am trying to create a method that fills an array with random integers with no duplicate elements. I'm having trouble making sure each element that is put into the new array is distinct.
Ex. if numOfDigits is 5, then I'd like something like [3][8][2][6][1]. At the moment it either outputs something like [9][0][1][0][0] or infinitely loops.
private static int[] hiddenSet(int numOfDigits){
int[] numArray = new int[numOfDigits];
int temp;
for (int i = 0; i < numArray.length; i++){
do {
temp = getRandomNum(10);
numArray[i] = temp;
} while (isDigitNew(numArray, temp));
//Each random num must be unique to the array
}
return numArray;
}
private static boolean isDigitNew(int[] numArray, int index){
for (int i = 0; i < numArray.length; i++) {
if (numArray[i] == index) {
return false;
}
}
return true;
}
One easy approach is to fill the array with distinct digits then shuffle it.
public static int[] getRandomDistinct(int length) {
Random rand = new Random();
int[] array = new int[length];
// Fill with distinct digits
for (int i = 0; i < length; i++) {
array[i] = i;
}
// Swap every element with a random index
for (int i = 0; i < length - 1; i++) {
int swapWith = i + rand.nextInt(length - i);
int tmp = array[i];
array[i] = array[swapWith];
array[swapWith] = tmp;
}
return array;
}
Your algorithm takes quadratic time at best. When the choice of random numbers becomes less looping may take ages. Even infinite might be possible.
Add a positive random number + 1 to the previous generated number. The desired range of numbers needs a bit of care.
At he end shuffle. If you start with a List, you can use Collections. shuffle.
You can use IntStream like this.
private static int[] hiddenSet(int numOfDigits) {
return IntStream.iterate(getRandomNum(10), i -> getRandomNum(10))
.distinct()
.limit(numOfDigits)
.toArray();
}
and
public static void main(String[] args) {
int[] a = hiddenSet(5);
System.out.println(Arrays.toString(a));
}
output:
[7, 4, 5, 0, 1]

How can I prevent the overlapping random numbers

How would i prevent duplicating numbers from random numbers.
I need to generate 5 numbers between 1 and 9 that are each different.
I would often get same numbers like 23334, how can i prevent that?
Any help would be great!
int num2 = (int) Math.round((Math.random()*9) +1);
int num1 = (int) Math.round((Math.random()*9) +1);
int num5 = (int) Math.round((Math.random()*9) +1);
int num3 = (int) Math.round((Math.random()*9) +1);
int num4 = (int) Math.round((Math.random()*9) +1);
One option is to use shuffle algorithm (e.g. Fisher-Yates shuffle ) to generate random sequence from 1 to 9, then take first 5 numbers of the sequence
Further explanation on StackOverflow: https://stackoverflow.com/a/196065/950427
Set<Integer> set=new HashSet<>();
while (set.size()<5) {
set.add( Math.round((Math.random()*9) +1));
}
After the set is filled you have 5 unique random numbers.
UPDATE: just to illustrate Jared Burrows' comment
Create a List includes the numbers that you want (1 to 9).
Generate random number from 0 to (size of the list minus 1).
Remove one element by index from the above generated random number. And add the removed element to a array which to be returned as a results
public static void main(String[] args) {
int []answers= returnRandomNonRepeatingNumbers(5,0,9);
for(int answer: answers) {
System.out.println(answer);
}
}
public static int[] returnRandomNonRepeatingNumbers(int sizeYouWant, int poolStart, int poolEnd) {
List<Integer> pool=new ArrayList<Integer>();
for(int i=poolStart;i<=poolEnd;i++) {
pool.add(i);
}
int []answers=new int[sizeYouWant];
for(int i=0;i<sizeYouWant;i++) {
//random index to be pick and remove from pool
int randomIndex = (int) Math.round((Math.random()*(pool.size()-1)));
answers[i]=pool.remove(randomIndex);
}
return answers;
}
If the number of possible random values is small, you want to use shuffle.
List<Integer> values = IntStream.range(0, 10).boxed().collect(toList());
Collections.shuffle(values);
values = values.subList(0, 5);
If the number of possible random values is large, you want to test adding them to a Set (or the original list if small enough)
Set<Integer> valueSet = new HashSet<>();
Random rand = new Random();
while(valuesSet.size() < 5) valuesSet.add(rand.nextInt(9) + 1);
List<Integer> values = new ArrayList<>(valueSet);
Collections.shuffle(values, rand);
Note: you need to shuffle the set as it doesn't preserve order. e.g. the numbers 1,2,3 will always come out in that order with HashSet, not 3,2,1.
Floyd's subset selection algorithm is designed to do exactly what you want, and is extremely efficient even for large sets. Selecting m items from a set of n is O(m) average running time, independent of n. Here's a Java implementation.
/*
* Floyd's algorithm to chose a random subset of m integers
* from a set of n, zero-based.
*/
public static HashSet<Integer> generateMfromN(int m, int n) {
HashSet<Integer> s = new HashSet<Integer>();
for (int j = n-m; j < n; ++j) {
if(! s.add((int)((j+1) * Math.random()))) {
s.add(j);
}
}
return s;
}
One possible approach to this problem can be divide & conquer. Step of following describes the approach:
Say m is the minimum & n is the maximum, within what i wanna get x number of randoms
Choose a random p between m & n. Save it to an array of answer. decrease x by 1 as we get one answer to our problem.
Now take a q a random number between m & p-1, another r a random number between p+1 & n. Fill up the answer array with q & r decrease x 1 for q and another 1 for the r.
Now carry on this process recursively, until the lower bound (m) & higher bound (n) becomes equal or x becomes 0.
Benefit: benefit of this approach is that, in worst case, it's runtime will be O(x), where x is the number of random number required. The best case scenarion is also o(x), as i have to find at least n number of random. These two comprise average case to θ(x) complexity.
import java.util.Random;
class GenerateDistinctRandom{
static int alreadyPut = 0;
static Random rand = new Random();
public static int[] generateDistinctRandom(int howMany, int rangeMin, int rangeMax)
{
int randomNumbers[] = new int[howMany];
GenerateDistinctRandom.recursiveRandomGenerator(rangeMin, rangeMax, randomNumbers, howMany);
return randomNumbers;
}
private static void recursiveRandomGenerator(int rangeMin, int rangeMax, int[] storage ,int storageSize)
{
if(rangeMax - rangeMin <= 0 || GenerateDistinctRandom.alreadyPut == storageSize)
{
return ;
}
int randomNumber = GenerateDistinctRandom.rand.nextInt(rangeMax-rangeMin) + rangeMin;
storage[GenerateDistinctRandom.alreadyPut] = randomNumber;
GenerateDistinctRandom.alreadyPut++;
//calling the left side of the recursion
recursiveRandomGenerator(rangeMin, randomNumber - 1, storage, storageSize);
recursiveRandomGenerator(randomNumber + 1, rangeMax, storage, storageSize);
}
public static void main(String []args){
int howMany = 5;
int distinctNumber[] = GenerateDistinctRandom.generateDistinctRandom(howMany 0, 9);
for(int i = 0;i < howMany;i++)
{
System.out.println(distinctNumber[i]);
}
}
}
I suppose you would need to store the ones that have been generated into an array and compare the new random number to the list to ensure it is unique.
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
int[] numbers = new int[5];
int tempNumber = 0;
for(int numberCounter = 0; numberCounter < numbers.length;)
{
tempNumber = (int) Math.round((Math.random()*9) +1);
if(!contains(numbers, tempNumber)){
numbers[numberCounter++] = tempNumber;
}
}
}
public static boolean contains(final int[] numbersArray, final int tempNumber) {
for (final int numberFromArray : numbersArray) {
if (numberFromArray == tempNumber) {
return true;
}
}
return false;
}
I notice you did not use an array in your example, so in case you do not know how to use them yet, you could also make 5 variables.
int randomNumber = 0;
int firstNumber = Math.round((Math.random()*9) +1);
int secondNumber = 0;
while(secondNumber == 0){
randomNumber = Math.round((Math.random()*9) +1)l
if(randomNumber != firstNumber){
secondNumber = randomNumber;
}
}
And you could continue making while statements like that. But if you are supposed to know about arrays, you should definitely be using one to store the numbers.
How about this?
package com.se;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class TestRandom {
List<Integer> comp = new ArrayList<>();
int listSize = 20;
public void doTask() {
Random ran = new Random();
int i = 0;
while(i < listSize){
int randomNumber = ran.nextInt(80) + 1;
if(!comp.contains(randomNumber)){
comp.add(randomNumber);
i++;
}
}
for(Integer num : comp){
System.out.println(num);
}
}
public static void main(String[] args) {
TestRandom testRandom = new TestRandom();
testRandom.doTask();
}
}

how to generate 50 random numbers between 10 and 99, no duplicates. [duplicate]

This question already has answers here:
Java - generate Random range of specific numbers without duplication of those numbers - how to?
(6 answers)
Closed 9 years ago.
Here's the code I have that solves my problem. But it seems really brute forced. Is there any optimized/elegant way to write this?
System.out.println("\n\nPart II: Let' put in a list of 50 random numbers between 10 to 99. No Duplicates!");
Linkedlist l1 = new Linkedlist();
Random rand = new Random();
for(int i = 0; i < 50; i++){
int num = rand.nextInt(89) + 10;//range between 10 and 99.
while(true){
if(!l1.search(num)){
l1.add(num);
break;
}
else
num = rand.nextInt(89) + 10;//recycle for new num
}//infinite loop until new non-duplicate random value is generated for the list.
}//for
Well there is a more cleaner way to do this that doesn't involve randomizing so much and output rejection. You can populate a List with the numbers you require, in this case:
List<Integer> numberList = new ArrayList<>();
for(int i=11; i<=99; i++){
numberList.add(i);
}
Then shuffle the List and pick first N numbers from it..
Collections.shuffle(numberList);
for(int j=0; j<50; j++){
System.out.println(numberList.get(j));
}
You have to know your set in advance though to be able to populate it.
Bounded Fisher-Yates shuffle. Runtime for the random sampling is linear in the number of elements you need, not the number of elements you're picking from. You don't waste any time shuffling the entire range of elements or rejecting elements that have already been picked.
int[] sample(int sampleSize, int startInclusive, int endExclusive) {
int[] samples = new int[sampleSize];
int[] range = IntStream.range(startInclusive, endExclusive).toArray();
Random random = new Random();
for (int i = 0, j = range.length; i < samples.length; i++) {
int k = random.nextInt(j--);
samples[i] = range[k];
range[k] = range[j];
}
return samples;
}
I would prefer using Set instead of a List as Set will automatically handle duplicates so that we need to worry about eliminating them by our own.
Try this:
Set<Integer> set = new HashSet<Integer>();
Random rand = new Random();
while(true) {
int num = rand.nextInt(89) + 10;// range between 10 and 99.
set.add(num);
if (set.size() == 50) {
break;
}
}
System.out.println(set);
Sets don't allow duplicates:
Set<Integer> s = new HashSet<Integer>();
Random rand = new Random();
while (s.size() < 50) {
int num = rand.nextInt(89) + 10;// range between 10 and 99.
s.add(num);
}
You could just use a Set, which will only allow unique values to be stored in it, this way you could just keep looping while the number of elements is less than 50...
Set<Integer> nums = new HashSet<>(50);
while (nums.size() < 50) {
nums.add((int)(10 + (Math.random() * 89)));
}
for (Integer num : nums) {
System.out.println(num);
}
This is a variation on #AnkurShanbhag's answer (I don't like while (true) loops ;)), so if you like, shoot them credit ;)
package com.project.stackoverflow;
import java.util.Random;
import java.util.Scanner;
import java.util.TreeSet;
public class RandomGenerator {
private Scanner s;
public TreeSet<Integer> compute() {
TreeSet<Integer> generatedList = new TreeSet<Integer>();
s = new Scanner(System.in);
System.out.println("Enter the lower bound for checking random numbers:");
long lowBound = s.nextLong();
System.out.println("Enter the upper bound for checking random numbers:");
long topBound = s.nextLong();
Random randomNumbers = new Random();
for (int i = 0; i < topBound; i++) {
if (generatedList.size() == 5) {
break;
} else {
generatorFunc(lowBound, topBound, randomNumbers, generatedList);
}
}
return generatedList;
}
public void generatorFunc(long lowBound, long topBound, Random randomNumbers, TreeSet<Integer> generatedList) {
long limit = topBound - lowBound;
long part = (long) (limit * randomNumbers.nextDouble());
int randomNum = (int) (part + lowBound);
generatedList.add(randomNum);
}
public void printList() {
TreeSet<Integer> testListVals = compute();
System.out.println("New" + testListVals);
}
public static void main(String[] args) {
RandomGenerator obj = new RandomGenerator();
obj.printList();
}
}

java random number chooser

I have a homework to write a method that returns a random number between
1 and 54, excluding the numbers passed in the argument. The method header is
specified as follows:
public static int getRandom(int... numbers)
I can't use anything more advanced than Single-Dimensional Arrays.
my code is:
public class PE13RandomNumberChooserVer2 {
public static void main(String[] args) {
int[] excludeNumbers = {1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 14, 15, 16, 17, 18};
int randomNumber = getRandom(excludeNumbers);
System.out.println();
System.out.println("Random number chosen: " + randomNumber);
}
public static int getRandom(int... excludeNumbers) {
int random = 1 + (int)(Math.random() * (54 - 1) + 1);
System.out.println("Numbers to exclude: ");
for (int i = 0; i < excludeNumbers.length; i++) {
System.out.print(excludeNumbers[i] + " ");
while (excludeNumbers[i] == random) {
random = 1 + (int)(Math.random() * 54);
System.out.println("\n(for test only) next random number: " + random);
}
}
return random;
}
}
a sample run showed that my logic is wrong:
(for test only) initial random number: 8
Numbers to exclude:
1 2 3 4 5 6 7 8
(for test only) next random number: 12
11 12
(for test only) next random number: 3
13 14 15 16 17 18
Random number chosen: 3
it checks only if random is equal to the current item in the array, it doesn't consider the case in which it can be equal to the previous item in the list that is already checked.
The end result for the random generated number should be a value different from the numbers in the array.
Any suggestions how to fix it are greatly appreciated.
The following will do it:
private final Random rand = new Random();
public int getRandom(int min, int max, int... excludeNumbers) {
int random = rand.nextInt(max - min + 1 - excludeNumbers.length) + min;
for (int exc : excludeNumbers) {
if (random >= exc) {
random++;
}
}
return random;
}
Observe how it only generates a single random number and doesn't require a rejection loop.
Note that both min and max are inclusive. Also note that excludeNumbers must appear in ascending order.
This
int random = 1 + (int)(Math.random() * (54 - 1) + 1);
and this
random = 1 + (int)(Math.random() * 54);
are strange and should coincide.
Latter one is correct.
Next your loops are wrong. Loops are for regenerating number in case it coincides with prohibited one. So you should place for inside while and place println outside all loops. for should serve to check all prohibited numbers for one generated and while should server as retriement loop.
Also you can use Random class.
THE CODE
public static void main(String[] args) {
int[] excludeNumbers = {1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 14, 15, 16, 17, 18};
int randomNumber;
System.out.println("Numbers to exclude: ");
for (int i = 0; i < excludeNumbers.length; i++) {
System.out.print(excludeNumbers[i] + " ");
}
// 100 tests
for(int i=0; i<100; ++i ) {
randomNumber = getRandom(excludeNumbers);
System.out.println();
System.out.println("Random number chosen: " + randomNumber);
}
}
public static int getRandom(int... excludeNumbers) {
int random;
// regeneration loop
regeneration: while(true) {
// generating a number
random = 1 + (int)(Math.random() * 54);
// checking of it's correctness
for (int i = 0; i < excludeNumbers.length; i++) {
// checking if number conincides for prohibited
if( excludeNumbers[i] == random ) {
// if number concided, then going to regeneration
continue regeneration;
}
// here number has not coincided
// but with just one of prohibites
// no decision here
}
// here all prohibited numbers checked and
// no coincidences found
// so generated number is good
System.out.println("\n(for test only) next random number: " + random);
break regeneration;
}
return random;
}
Try this, which simply keeps trying until you get an acceptable number.
List<Integer> nums = Arrays.asList(excludedNumbers);
while (true) {
Random random = 1 + (int)(Math.random() * 54);
if (!nums.contains(random))
return random;
}
The method would be cleaner if you passed exclude numbers as a list.
The techniques that keep retrying until hitting an allowed number are crude and turn into a crying misery as the number of allowed numbers approaches 1. A much more elegant way is this:
create a boolean[54];
set each excluded element to true;
choose a random number r from a range as large as the number of allowed choices (54 - number of exclusions);
return the rth false element in the boolean array.
Note: this algorithm is the best fit when you can cache the boolean array; for your exact case (the function receives a new array every time) NPE's solution is superior.
Look into java.util.random, it has a method that provides a random integer between 0 and your specified number. I can't give you an example because I'm typing this from my phone at the moment, but if you were to get it between 1 and 54 I would get a random number between 0 and 53 and add 1 to the result.
I am also teaching myself Java right now. I spend several days on this problem already while there is no answer available yet online. The solution above is too advanced for me so far. Here is my solution finally, which employ basic array knowledge only
public class Q6_13 {
public static void main(String[] args) {
int[] excludeNumbers = {1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 14, 15, 16, 17, 18};
System.out.println (getRandom(excludeNumbers));
}
public static int getRandom(int...numbers) {
int n = (int)(Math.random() * 54) + 1; ;
boolean newRandom = false;
boolean getNew = false;
while (getNew == false) {
for (int i = 0; (i < numbers.length) && newRandom == false; i++) {
if (n == numbers[i]) {
newRandom = true;
}
}
if (newRandom) {
n = (int)(Math.random() * 54) + 1;
getNew = false;
newRandom = false;
}
else
getNew = true;
}
return n;
}
}
public static int getRandom(int... numbers) {
final Random random = new Random();
final int[] arr1 = new int[54];
int count = 54;
for(int i = 0; i < arr1.length; ++i) {
arr1[i] = i + 1; // good luck doing this with foreach
}
for(int i = 0; i < numbers.length; ++i) {
final int n = numbers[i];
if(arr1[n] != 0) {
--count;
}
arr1[n] = 0;
}
final int[] arr2 = new int[count];
for(int i = 0, j = 0; i < arr2.length; ++i, ++j) {
if(arr1[j] == 0) {
++j;
}
else {
arr2[i] = arr1[j];
}
}
return arr2[random.nextInt(count)];
}
public class Compute {
public static void main(String[] args) {
int[] values = {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41};
int x = 1+ (int) (Math.random()*54);
System.out.println("Value: "+getRandom(x,values));
}
public static int getRandom(int a, int... numbers){
System.out.println("x1: "+a);
for(int j=0;j<numbers.length;){
//System.out.println("Numbers: "+numbers[j]);
if(numbers[j]==a){
a = 1 + (int) (Math.random()*54);
System.out.println("x2: "+a);
j=0;
continue;
}
j++;
}
return a;
}
}

Arrays.sort not filling array, overwriting values that are already in the array

I need to generate an array int[] randomNumbers of random numbers with no duplicates. To do this, I make an array with all values that can go into randomNumbers, then use a random number generator to pick one out of the list, check if it's already in randomNumbers, and if it isn't, put it in randomNumbers.
(I want numbers between 1 and max, not 0 and max-1)
To be able to use Arrays.sort(int[]), the list needs to be sorted. So I use a third array, with the same values as randomNumbers called sortedNumbers, and sort it on every iteration:
public int[] uniqueRandom(int max, int numRequired) {
if (max < numRequired) {
numRequired = max;
}
int[] randomNumbers = new int[numRequired];
int[] sortedNumbers = new int[numRequired];
int[] sequentialNumbers = new int[max];
for (int i = 1; i < max; i++) {
sequentialNumbers[i] = i;
System.out.println(sequentialNumbers[i]);
}
int p = 0;
while (p < numRequired) {
int j = r.nextInt(max) + 1;
System.out.println("J:" + j);
if (Arrays.binarySearch(sortedNumbers, j) >= 0) {
System.out.println("Number Found:" + Arrays.binarySearch(randomNumbers, j));
} else {
randomNumbers[p] = j;
sortedNumbers[p] = j;
Arrays.sort(sortedNumbers);
for (int i = 0; i < randomNumbers.length; i++) {
System.out.println("rNum[" + i + "]:" + randomNumbers[i]);
}
System.out.println("\n");
for (int i = 0; i < randomNumbers.length; i++) {
System.out.println("sNum[" + i + "]:" + sortedNumbers[i]);
}
p++;
}
}
return randomNumbers;
}
My issue is that I'm getting an output where sortedNumbers is overwriting values. For uniqueRandom(5, 5) the output is:
J:2
rNum[0]:2
rNum[1]:0
rNum[2]:0
rNum[3]:0
rNum[4]:0
sNum[0]:0
sNum[1]:0
sNum[2]:0
sNum[3]:0
sNum[4]:2
J:2 // 2 already in the list, try again
J:2
J:4
rNum[0]:2
rNum[1]:4
rNum[2]:0
rNum[3]:0
rNum[4]:0
sNum[0]:0
sNum[1]:0
sNum[2]:0
sNum[3]:2
sNum[4]:4
J:5
rNum[0]:2
rNum[1]:4
rNum[2]:5
rNum[3]:0
rNum[4]:0
sNum[0]:0
sNum[1]:0
sNum[2]:2
sNum[3]:4
sNum[4]:5
J:2
J:3
rNum[0]:2
rNum[1]:4
rNum[2]:5
rNum[3]:3
rNum[4]:0
sNum[0]:0 // Should be:
sNum[1]:0 // 2
sNum[2]:2 // 3
sNum[3]:3 // 4
sNum[4]:5 // 5
J:4
rNum[0]:2
rNum[1]:4
rNum[2]:5
rNum[3]:3
rNum[4]:4
sNum[0]:0
sNum[1]:0
sNum[2]:2
sNum[3]:3
sNum[4]:4
So you can see the issue. I'm using java 1.7, and have no idea why it's doing this!
To solve your problem I would use a Set, that assure us to have unique results.
Below snipest will generate array with required number of unique integers.
Set<Integer> uniqueNumbers = new HashSet<Integer>();
Random r = new Random();
while(uniqueNumbers.size() < numRequired) {
uniqueNumbers.add(r.nextInt(maxRandom) + 1);
}
return uniqueNumbers.toArray(new Integer[0]);
You are putting the new number into both arrays using the same index. Your rNum array is filling from top down, but the sorted array is not: Each time you sort it, the new value moves down in the array and the zeros are always at the top. I think you could fix it by always putting the new number in the first position of the sorted array:
sortedNumbers[0] = j;
When you input J=5
the sortedNUm[] is
sNum[0]:0
sNum[1]:0
sNum[2]:2
sNum[3]:4
sNum[4]:5
next when you input J=3 (your p=3)
after
sortedNumbers[p] = j;
your sNUM[3] which is 4 is replaced by 3
hence after sorting it becomes
sNum[0]:0 // Should be:
sNum[1]:0 // 2
sNum[2]:2 // 3
sNum[3]:3 // 4
sNum[4]:5 // 5
notice 4 is not present
I suggest you initialize the array to -1 or 0 and add the variables at the start of array
like
sortedNumbers[0]=j;
and after Arrays.sort(); the first position will always be empty to add more numbers
While it doesn't answer the question, here is an alternative which is O(n) and work well provided max is not large.
public static void main(String[] args) {
System.out.println(Arrays.toString(uniqueRandom(20, 10)));
}
public static int[] uniqueRandom(int max, int numRequired) {
int[] possible = new int[max];
int[] ret = new int[numRequired];
for (int i = 0; i < max; i++)
possible[i] = i + 1;
Random r = new Random();
int numLeft = max;
for (int i = 0; i < numRequired; i++) {
int idx = r.nextInt(numLeft);
ret[i] = possible[idx];
if (idx < --numLeft)
possible[idx] = possible[numLeft];
}
return ret;
}
prints
[4, 10, 12, 19, 8, 3, 15, 1, 14, 7]
What I am trying to say is that perhaps you could make it simpler.
There are a few issues with your code:
since you only increment p when the new number j doesn't already exist in the arrays, that, combined with the fact that you sort the sortedArray first leads to the value actually being placed sometimes over an existing value (which shifted position due to the sort)
I don't understand what's the use of the sequentialNumbers array...
Here's an example which should work:
private static Random r = new Random();
public static void main(String[] args) {
System.out.println(Arrays.toString(uniqueRandom(10, 10)));
}
public static int[] uniqueRandom(int max, int numRequired) {
if (max < numRequired) {
numRequired = max;
}
int[] randomNumbers = new int[numRequired];
int[] sortedNumbers = new int[numRequired];
Arrays.sort(sortedNumbers);
int p = 0;
while (p < numRequired) {
int j = r.nextInt(max) + 1;
if(Arrays.binarySearch(sortedNumbers, j)<0) {
randomNumbers[p] = j;
System.arraycopy(randomNumbers, 0, sortedNumbers, 0, randomNumbers.length);
Arrays.sort(sortedNumbers);
p++;
}
}
return randomNumbers;
}

Categories