on the first iteration- I want to create a random number from 0..10
This is how I've implement it-
int generator= (int)(Math.random() * (10));
On the first iteration I want to create another random number, but without one of the values.
For example I would like the random number without the number 4.
only 1,2,3,5,6,7,8,9,0
How can I remove one of the values from the numbers 0..10 when I generate a random number?
1st Way: -
You can also maintain a List of all the numbers. Then use Collections.shuffle to shuffle the list and get the first element. And remove it.
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(4);
list.add(2);
list.add(3);
System.out.println("Original List: " + list);
Collections.shuffle(list);
System.out.println("Shuffled List: " + list);
int number1 = list.remove(0); // Remove the first value
System.out.println("Number removed: " + number1);
Collections.shuffle(list);
System.out.println("Shuffled List: " + list);
number1 = list.remove(0);
System.out.println("Number removed: " + number1);
OUTPUT: -
Original List: [1, 4, 2, 3]
Shuffled List: [4, 3, 1, 2]
Number removed: 4
Shuffled List: [1, 3, 2]
Number removed: 1
2nd Way: -
A better way would be to generate a random number from 0 to the size of the list, and get the value of that index and remove it.
int size = list.size();
Random random = new Random();
for (int i = 0; i < size; i++) {
int index = random.nextInt(list.size());
int number1 = list.remove(index);
System.out.println(number1);
}
NOTE: -
If you want to exclude a fixed set of numbers from being generated, then you can have those numbers in a list. And then remove all elements of that list from your list of numbers. And then use any of the approach above.
int generator= (int)(Math.random() * (10));
if (generator >= 4) generator++;
This will include the number 10 as a possible outcome, if you do not want this, multiply by 9 instead of 10.
You could store the values in a list, and generate a random index to take from that list.
private Random random = new Random();
private ArrayList<Integer> values = new ArrayList<Integer>();
public static int nextInt() {
if (values.size() > 0) {
return values.remove(random.nextInt(values.size()));
} else {
throw new RuntimeException("no values possible");
}
}
Random.nextInt(10)==number generate again
public int generateExcept(int number) {
Random random = new Random();
int generated = 0;
while ((generated = random.nextInt(11)) == number) {
}
return generated;
}
As quoted by OP
On the first iteration I want to create another random number, but without one of the values
If I understand correctly This is single operation not repetitive operation.
Without Regeneration
public static int generateExcept(int number, int max) {
Random random = new Random();
int generated = 0;
if ((generated = random.nextInt(max - 1)) == number) {
generated++;
}
return generated;
}
Random is always generated max-1 because we want to increment by one
There are two basic efficient approaches:
1 - Generate an array of valid values (0 to 10 except 4), and use the randomizer to pick an index on that array. An example follows:
Random random = new Random();
int[] unwanted = {4};
int[] values = new int[10-unwanted.length];
for(int i=0; i<10-unwanted.length; i++){
for(int curr : unwanted){
if(i == curr) continue;
}
values[i] = i;
}
int result = values[random.nextInt(10-unwanted.length)];
2 - Follow Simon André's approach.
What you could do (perhaps there is a cleaner way of handling this) is to check the 2nd generated number to see if it matches the first, and if it does, just have it run the random num. generator again.
A simple if...else loop should take care of it.
int excluded[] = { 1,4,3};
Random r = new Random();
int generator;
do {
generator= r.nextInt(10);
} while (! Arrays.asList(excluded).contains(generator) )
Related
Is there a way where you can use Math.random to prints the element in a given array?
int[] list = new int[] {1,2,3};
So the output will be like
2,1,3
or
3,1,2
or
2,3,1
Perhaps you can approach it by shuffling your array then print it. If the original should not be modified, you can make a copy and then shuffle the copy.
There are well-known algorithms for shuffling array (or a deck of cards). One can be found here. An implementation in java looks like this:
static void shuffleArray(int []array) {
int length = array.length;
for (int i = length -1; i > 0; i--) {
// generate a random 0 <= j < i
int j = (int)(Math.random() * i);
// swap elements at i and j
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
The approach proposed in most answers is extremely inefficient, as it works in O(N2) time. Think about it: at first you'll generate unused indexes with one attempt, but closer to the end, when almost all array is processed, it will require nearly N steps to generate next unused index.
The optimal O(N) approach is to create shuffled array of indexes (0..N) where each index appears only once and then process your original array in the order of shuffled indexes. Each step requires O(N) time, so the whole algorithm is O(N).
int[] input = new int[]{5, 4, 3, 6, 2, 1};
int []indices = new int[input.length];
//Fisher-Yates shuffle
Random rnd = new Random();
for (int i = 0; i < indices.length; i++) {
int j = rnd.nextInt(i + 1);
indices[i] = indices[j];
indices[j] = i;
}
for (int i : indices) {
System.out.println(input[i]);
}
I didn't use Collections.shuffle, as it would require usage of Collection and thus wrapped Integer elements, which is very inefficient comparing to the plain int array.
Also, if you are ok with modifying your original array, you can just shuffle it in place (using the same Fisher-Yates shuffle) and then consume it while traversing.
UPD: Replaced shuffling array of indices with shuffled initialization.
Since you have java 8, you can take advantage of the beautiful Stream API.
In short, you can do:
new Random().ints(1, 500).limit(500).forEach(p -> System.out.println(list[p]));
Where 1 is the lowest int generated (inclusive) and 500 is the highest (exclusive). limit means that your stream will have a length of 500, maybe in that argument you want to put list.length.
For your case:
int[] list = new int[] {1,2,3,4,5,6};
new Random().ints(0, list.length).limit(10).forEach(p -> System.out.println(list[p]));
Prints: 5 2 5 4 6 3 3 5 6 4 (Obviously will not print the same numbers for you)
Create a random integer that may be as high as the length of the array - 1. If the random integer is equal to a previous used random integer -- known by storing used integers in an array -- create a new random integer. Otherwise, print the string correlated with that index specified by the random integer. If the length of the array storing the used random integers is equal to the length of the array of strings, stop the process.
This should print all your strings only once each and randomly.
Here is the solution
public static void main(String[] args) {
int[] list = new int[] { 1, 2, 3 };
int[] aux = new int[list.length];
int countTimes = 0;
while (countTimes < list.length) {
int position = new Random().nextInt(list.length);
if (aux[position] != list[position]) {
System.out.println(list[position]);
aux[position] = list[position];
countTimes++;
}
}
}
As I said in the comments. This answer will work.. All you need to do is track the indices that it accessed so you don't repeat them or remove that element from the array.
void printRandom(int[] array) {
if (array.length == 0)
return;
Random rand = new Random();
int rnd = rand.nextInt(array.length);
int element = array[rnd];
array = ArrayUtils.removeElement(array, element);
System.out.print(element);
printRandom(array);
}
Just repeat this process until all elements are removed. Obviously add checks to prevent errors and keep in mind I haven't used JAVA in a long time so post back if you have issues!
Lastly keep in mind this deletes the array so you may want to wrap this code in a function and then copy the array as a local variable so you can reuse the original as needed
In this case we can print random value from array using like below :
Steps:
Create list object of Integer to hold printed indices
Get random number and check whether this index is already printed or not
if not printed then add it in list and print value from array using this index
if list size and array length is equal then terminate the loop
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class RandomIndices {
public static void main(String[] args) {
int[] list = new int[]{1, 2, 3};
Random random = new Random();
List<Integer> randomIndices = new ArrayList<>(); //to hold indices which are already printed
boolean isRemain = true;
while (isRemain) {
int randomIndex = random.nextInt(list.length);
if (!randomIndices.contains(randomIndex)) { //check random index value of array is printed or not
randomIndices.add(randomIndex);
System.out.println(list[randomIndex]);
}
if (randomIndices.size() == list.length) {
isRemain = false;
}
}}
}
Implement a simple "do while" statement to prevent duplicate numbers from showing up out of your array (I used a StringArray - but an IntegerArray would work the same way - as a side note, I can place the complete code up here but didn't want to do so if it didn't apply. I use a drop-down to select how many random words to generate - then display that set of true RANDOM words (non-repeated):
final Random rand1 = new Random();
final Random rand2 = new Random();
final int rndInt1 = rand1.nextInt(getResources().getStringArray(R.array.words).length);
int rndInt2 = rand2.nextInt(getResources().getStringArray(R.array.words).length);
if (rndInt1 == rndInt2){
do {
rndInt2 = rand2.nextInt(getResources().getStringArray(R.array.words).length);
}while (rndInt1 == rndInt2);//if indexes are equal - re-run the array search
}
outString = getResources().getStringArray(R.array.words)[rndInt1];
outString += ", " + getResources().getStringArray(R.array.words)[rndInt2];//concatenate the list
textWord = (TextView) findViewById(R.id.textWords);//An empty text field in my layout
textWord.setText(outString);//Set that empty text field to this string of random array elements
it's my first time I ask here question.
I wanna make ArrayList with 10 unique int numbers from 0 to 9.
I do next steps:
Create empty Arraylist
Add first random number, so I can check for repetition later
Next I create new random int value, check if I've already have this one in ArrayList. If I have - I try another number, if I have not - I add this number.
If I got 10 numbers, I stop the loop
My code:
public static void main(String[] args) {
Random rd = new Random();
ArrayList<Integer> list = new ArrayList<Integer>();
int q = rd.nextInt(10);
list.add(q);
while (true) {
int a = rd.nextInt(10);
for (int b=0;b<list.size();b++){
if (a == list.get(b)) break;
else list.add(a);
}
if (list.size() == 10) break;
}
System.out.println(list);
}
But all I see in console is endless process.
The question is - is there another way to make ArrayList with 10 unique numbers (0 to 9)?
Use Collections.shuffle after initializing your ArrayList with the numbers.
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 10; i++)
{
list.add(i);
}
Collections.shuffle(list);
That will run in linear time because ArrayList is RandomAccess.
Using Java 8 Streams
List<Integer> shuffled =
// give me all the numbers from 0 to N
IntStream.range(0, N).boxed()
// arrange then by a random key
.groupBy(i -> Math.random(), toList())
// turns all the values into a single list
.values().flatMap(List::stream).collect(toList());
I tried to generate a sorted list of random data with no duplicates in descending order for my array. It also returns number of duplicates, but it keeps printing out nothing but zero .... Can anyone help me please :(
// 2. Ask the user for size of arbitrary numbers.
System.out.print("Please enter a size for arbitray numbers: ");
int size = indata.nextInt();
int [] SortedNumbers = new int [size];
// 3. Process arbitrary numbers and remove all duplicates
int numDuplicates = generate_data(SortedNumbers);
// 4. Print the numbers and number of duplicates
printArray(SortedNumbers, numDuplicates);
and here is the random method
public static int generate_data (int [ ] list){
int duplicates = 0;
Random random = new Random();
System.out.println(n[random.nextInt(n.length)]);
return duplicates;
}
here is the print_array method
public static void printArray(int [] list, int duplicates) {
// Additional code required
System.out.println("\nSize of array: " + list.length + " .Numbers of duplicates: " + duplicates); for (int i = 0; i<list.length; i++){
System.out.printf("%7d", list[i]);
if ((i + 1) % 10 == 0){
System.out.println();
}
}
}
random.nextInt(n.length)
gives you a random index of your array.
But printing the value corresponding to this index, will always give you 0. As you never store any other value in the array.
You should rather do something like this :
int[] list = new int[10];
int duplicates = 0;
Random random = new Random();
for (int i = 0; i < list.length; i++) {
int nextVal = random.nextInt(list.length);
System.out.println("list["+i+"] = "+ nextVal);
// test duplicates
for (int index = 0; index < i; index++) {
if (list[index] == nextVal) {
duplicates++;
break;
}
}
list[i] = nextVal;
}
return duplicates;
Your generate_data method always returns 0, since the local field duplicates is initialized with a 0 value and never changed.
The n field referenced by your generate_data method (which you haven't posted) is likely to be an int[], but its elements might not have been initialized (hence the print out will print default value 0, if within array index).
Hence your numDuplicates local field is always 0 too.
Notes
Your Random initialization is not performing. You should initialize a static Random object in your class and re-use it, instead of re-initializing every time in your generate_data method.
You probably want to have a look at coding conventions for Java in terms of field naming
You might want to post the code in your printArray method as well
I need to make a typical integer filled array with 10 random non repeating numbers from 0 to 20. Also, I need to be able to modify this so I can exclude some random numbers from 0 to 20.
How can I do this?
You can do this in three easy steps:
Build a list with all the candidate numbers you want
Use Collections.shuffle to shuffle that list
Use the n first elements of that shuffled list.
First build a list of size 20 with values 0,...,19
Then shuffle() it
And last - take the sublist containing first 10 elements.
This Method will work for you. It generate 10 unique random numbers from 0 to 20.
public static int[] getRandomArray(){
int randomCount =10;
int maxRandomNumber = 21;
if(randomCount >maxRandomNumber ){
/* if randomCount is greater than maxRandomNumber
* it will not be possible to generate randomCount
* unique numbers
**/
return null;
}
HashMap<Integer, Integer> duplicateChecker = new HashMap<Integer, Integer>();
int[] arr = new int[randomCount ];
int i = 0;
while(i<randomCount ){
// Generate random between 0-20, higher limit 21 is excluded
int random = new Random().nextInt(maxRandomNumber );
if(duplicateChecker.containsKey(random)==false){
duplicateChecker.put(random, random);
arr[i]=random;
i++;
}
}
return arr;
}
* Edited: To make the method deterministic. And Avoid the chance of infinite loop
public static int[] getRandomArray(){
int randomCount =10;
int maxRandomNumber = 21;
if(randomCount >maxRandomNumber ){
/* if randomCount is greater than maxRandomNumber
* it will not be possible to generate randomCount
* unique numbers
**/
return null;
}
ArrayList<Integer> arrayList = new ArrayList<Integer>();
// Generate an arrayList of all Integers
for(int i=0;i<maxRandomNumber;i++){
arrayList.add(i);
}
int[] arr = new int[randomCount ];
for(int i=0;i<randomCount;i++){
// Generate random between 0-20, higher limit 21 is excluded
int random = new Random().nextInt(arrayList.size());
// Remove integer from location 'random' and assign it to arr[i]
arr[i]=arrayList.remove(random);
}
return arr;
}
What about making an arraylist of numbers upto 20, and after each random number call you remove the number from the list and into the array.
example
Random r = new Random();
int[] myArray = new int[10];
ArrayList<Integer> numsToChoose = new ArrayList<Integer>();
int counter = 0;
for(int i = 0; i < 21; i++)
{
numsToChoose.add(i);
}
while(numsToChoose.size() > 11)
{
myArray[counter] = numsToChoose.remove(r.nextInt(numsToChoose.size()));
counter++;
}
That way it should only loop 10 times, I may be wrong though.
Hope it helps
EDIT: And in order to modify this to exclude certain numbers, you would just need a method that takes an array that contains said numbers as a parameter, and loop through it removing each number from the arraylist before you generate your random numbers.
Most of the other responses offer the Collections.shuffle method as a solution. Another way, which is theoretically faster is the following:
First lets build the list:
public class RandomWithoutReplacement {
private int [] allowableNumbers;
private int totalRemaining;
/**
* #param upperbound the numbers will be in the range from 0 to upperbound (exclusive).
*/
public RandomWithoutReplacement ( int upperbound ) {
allowableNumbers = new int[ upperbound ];
for (int i = 0; i < upperbound; i++) {
allowableNumbers[i] = i;
}
totalRemaining = upperbound;
}
}
Next lets consider what we need to do when we need to get the next number.
1) When we request another number, it must be chosen from any one of the available, uniformly.
2) Once it is chosen, it must not repeat again.
Here is what we can do:
First, choose a number at random from the allowableNumbers array.
Then, remove it from the array.
Then remove the number at the end of the array, and place it in the position of the number we are to return.
This ensures all of the 2 conditions we have placed.
public int nextRandom () {
//Get a random index
int nextIndex = (int) ( Math.random() * totalRemaining );
//Get the value at that index
int toReturn = allowableNumbers [ nextIndex ];
//Find the last value
int lastValue = allowableNumbers [ totalRemaining - 1 ];
//Replace the one at the random index with the last one
allowableNumbers[ nextIndex ] = lastValue;
//Forget about the last one
totalRemaining -- ;
return toReturn;
}
With that, your function is almost complete.
I would add a couple more things just in case:
public boolean hasNext () {
return totalRemaining > 0;
}
And at the beginning of the actual function:
public int nextRandom () {
if (! hasNext() )
throw new IllegalArgumentException();
// same as before...
}
That should be it!
Well, I could't help it not to post my solution which is storing a sequance of numbers into twice as many random locations first. Then compacts it into the resultting array.
int[] myRandomSet = generateNumbers(20, 10);
...
public int[] generateNumbers(int range, int arrayLenght){
int tempArray[];
int resultArray[];
int doubleLocations;
Random generator = new Random();
doubleLocations = range * 2;
tempArray = new int[doubleLocations];
resultArray = new int[arrayLenght];
for (int i=1; i<=range; i++){
if (i != 5 && i != 13){ //exclude some numbers
do{
r = generator.nextInt(doubleLocations);
}while(tempArray[r]!=0);
tempArray[r] = i; //enter the next number from the range into a random position
}
}
int k = 0;
for (int i=0; i<(doubleLocations); i++){
if(tempArray[i] != 0){
resultArray[k] = tempArray[i]; //compact temp array
k++;
if (k == arrayLenght) break;
}
}
return resultArray;
}
Sounds simple enough...but I've been plugging away at this, trying to find the one and all solution.
For a range of numbers, say 1-12, I want to generate a random sequence within that range, and include 1 and 12.
I don't want duplicate numbers though.
So I would want something like this - 3,1,8,6,5,4 ..and so on, every number from 1-12.
Then I want to put these random numbers into an Array and use that array to 'randomly' select and display some items (like inventory pulled from database) on a jsp page.
The problem with what I've tried thus far, is that there are a lot of duplicate numbers being generated...or, not ALL of the numbers are chosen.
Is there a simple solution to this problem?
Edit
Test#1 using Collections and shuffle() method -
ArrayList<Integer> list = new ArrayList<Integer>(10);
for(int i = 0; i < 10; i++)
{
list.add(i);
}
Collections.shuffle(list);
String[] randomNumbers = (String[])list.toArray();
for(int i = 0; i < 10; i++)
{
out.print(randomNumbers[i]+"<br>");
}
The result was a sequence with duplicate values -
chose = 3
chose = 8
chose = 7
chose = 5
chose = 1
chose = 4
chose = 6
chose = 4
chose = 7
chose = 12
Test #2 - using Random math class
int max = 12;
int min = 1;
int randomNumber = 0;
String str_randomNumber = "";
for(int i=0; i<10; i++) {
//int choice = 1 + Math.abs(rand.nextInt(11));
int choice = min + (int)(Math.random() * ((max - min) + 1));
out.print("chose = "+choice+"<br>");
}
The result was just like using Collections.shuffle().
You can fill an array with all values from 1 to 12 and then shuffle them (see e.g. Why does Collections.shuffle() fail for my array?)
You can put all numbers from 1 to 12 in order into array and then use some shuffling algorithm to randomize the order of them e.g. http://www.leepoint.net/notes-java/algorithms/random/random-shuffling.html.
Random number generation allows for duplications. If you want a range of random numbers without duplication, I suggest the following:
Generate a random number (I will refer to this a numberX).
Add to a Set object.
Check the size of the Set object, if it is the desired size, you are done. If it is smaller than the desired size, goto step 1
If you are using MySQL or SQLLite as your database you can do this randomization at the SELECT query level by using ORDER BY RAND() for restricting to 1-12 you can put a where clause WHERE ID >=1 AND ID <=12 ORDER BY RAND()
This is a utility method for creating a random Integer number :
public static int randomInteger(int min, int max) {
Random rd = new Random();
return rd.nextInt((max - min) + 1) + min;
}
This is an algorithm that always produces a unique Set of integers:
public static Set<Integer> makeRandomSet(int howManyNumber, int startNumber, int endNumber){
Set<Integer> integerSet = new HashSet<>();
boolean couldBeAdded = false;
for(int i=0; i< howManyNumber; i++) {
while (!couldBeAdded) {
Integer randomInt = randomInteger(startNumber, endNumber);
couldBeAdded = integerSet.add(randomInt);
}
couldBeAdded = false;
}
return integerSet;
}
We made use of add method return type to check the duplicate value within our Set.
And here is the test code:
public static void main(String[] args) {
Set<Integer> randomSet = makeRandomSet(6, 1, 54);
System.out.println(randomSet);
}
The output of the above code is 6 random unique integers number
between 1 and 54
You could just put all the numbers you want in a List and then order the List randomly and then convert the randomly ordered list to an array, e.g.
List<Integer> list = new ArrayList<Integer>();
for (int i = 1; i <= 12; i++) {
list.add(i);
}
Collections.sort(list, new Comparator<Integer>() {
#Override
public int compare(Integer o1, Integer o2) {
return Math.random() > 0.5 ? 1 : -1;
}
);
Integer[] array = list.toArray(new Integer[list.size()]);