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());
Related
This question already has answers here:
Java Array of unique randomly generated integers
(10 answers)
Closed 5 years ago.
i want to create an array of 10000 unique random elements. Till now i only figure out how to create random integers and fill an array and finding the doubles and deleted them. But this decrease the size of the array which i dont want it.
So the question is how i can fill an array with unique integers as elements without decreasing the size of the array.
You could use this code. Usage of Set will eliminate duplicates and you are fetching random numbers until you get 10000 different random integers.
Set<Integer> numbers = new HashSet<>();
Random r = new Random();
while (numbers.size() < 10000) {
numbers.add(r.nextInt(100000));
}
Integer[] a = new Integer[numbers.size()];
a = numbers.toArray(a);
I found this great solution:
This solution doesn't need any Collection class.
public static int[] createRandomNumbers(int howMany) {
int n = howMany + 1;
int a[] = new int[n];
for (int i = 0; i < n; i++) {
a[i] = i;
}
int [] result = new int[n];
int x = n;
SecureRandom rd = new SecureRandom();
for (int i = 0; i < n; i++) {
int k = rd.nextInt(x);
result[i] = a[k];
a[k] = a[x-1];
x--;
}
return result;
}
System.out.println(Arrays.toString(createRandomNumbers(10000)));
Reference: Best way to create a list of unique random numbers in Java
Hope it helps
Try this logic:
USE AN ARRAYLIST ENTIRELY, THEN CONVERT TO AN ARRAY AT THE END OF THE ENTIRE OPERATION.
Declare an arraylist
For every random number generated, check if the number already exists in the arraylist (using the .contains() method). If it does, repeat the process, else, move to the next number.
Code example:
Arraylist<Integer> arr = new Arraylist<>();
arr.add(generate()); //I included this line so that the arraylist won't be empty
//Note that the method *generate()* generates a new random number
for(int i = 0; i < 9999; i++){
int next = generate(); //the method that generates your number
if(arr.contains(next)){
i--; //The entire operation will be repeated for this index.
}
else{
arr.add(next); //Add the number to the arraylist
}
}
int[] finalArray = arr.toArray(); //Your final resultant array!
I hope this helps.. Merry coding!
You can use Set. This Collection that contains no duplicate elements.
Documentation https://docs.oracle.com/javase/7/docs/api/java/util/Set.html
Set<Integer> numbers = new HashSet();
do {
numbers.add(ThreadLocalRandom.current().nextInt());
} while(numbers.size() < 10000);
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
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) )
i want a program that can add the generated random numbers(unique not repeating) to 2 arrays alternatively...
this is what i have done so far:
int n = 56,m=0;
int e=0,f=0;
int[] deck1 = new int[n];
int[] deck2 = new int[m];
Random rng = new Random();
List<Integer> generated = new ArrayList<Integer>();
for(int i=1;i<=53;i++)
{
while(true)
{
next = rng.nextInt(53) + 1;
if (!generated.contains(next))
{
generated.add(next);
break;
}
}
for(int t = 2;t<=i;t++)
if(t%2==0)
{deck1[e]=next;e++;}
else
{deck2[f]=next;f++;}
}
but i am not getting the result. please help.
thanks.
You can fix your immediate problem by forgetting about the inner for loop (iterating over t) and instead compute using i:
if ( i % 2 == 0 ) {
deck1[e] = next;
e++;
} else {
//...
The problem is that currently at each iteration of the loop, you add the element to each array many times (up to i times).
Some other suggestions:
Make generated a Set<Integer> (HashSet<Integer>), it is much better suited to this task
A better algorithm would be to construct a List<Integer> containing the numbers 1 through 53 and shuffle (e.g. with Collections.shuffle()). Then you could just add the first half of the list to deck1 and the second half to deck2.
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()]);