I'm trying to get a a list of random number and put it in queue without any repetition of the random number.
int number = 40;
for (int j = 0; j<number; j++)
{
int pick = random.nextInt(number);
myQueue.add(Integer.toString(pick));
}
System.out.println("the queue size: "+myQueue.size());
Iterator it = myQueue.iterator();
while(it.hasNext()){
String iteratorValue = (String)it.next();
System.out.println("queue next value: "+iteratorValue);
}
with the above code, I got some repetition of the random number
anyone know how to do it??
How about this:
List<String> list = new ArrayList<String>(number);
for (int i = 0; i < number; i++)
list.add(Integer.toString(i));
Collections.shuffle(list);
myQueue.addAll(list);
"Adding unique random numbers" in some range is equivalent to adding all of the numbers in the range and then shuffling the result.
Create a Set and add you numbers to it as you generate them. The each time you generate a new number check if the Set already contains that value. Continue generating new numbers and checking the set until you find one that is not already there.
Something along these lines... (Note that Set.add(...) returns false if the value is already in the Set, so the do-while loop continues until a unique number is generated.)
int number = 40;
Set mySet = new HashSet();
for (int j = 0; j<number; j++)
{
Integer pick;
do{
pick = random.nextInt(number);
} while(!mySet.add(pick));
myQueue.add(Integer.toString(pick));
}
System.out.println("the queue size: "+myQueue.size());
Iterator it = myQueue.iterator();
while(it.hasNext()){
String iteratorValue = (String)it.next();
System.out.println("queue next value: "+iteratorValue);
}
Though as mentioned in by A. R. S., you don't seem to be looking for a random unique number, but rather a randomly shuffled list of all numbers between 0 and 40. If that is the case, use his/her solution as it is a better way to achieve that goal.
If there is a small range of the random numbers, then you can simply generate list with available values and use Collections.shuffle on the list.
Related
I made a code that could generate random numbers, but my issue is that sometimes it would repeat two or three numbers from time to time.
int winnum[] = new int[6];
System.out.print("Lotto winning numbers: ");
for(int i = 0; i < winnum.length; i++){
winnum[i] = 0 + (int)(Math.random() * 42);
System.out.print(winnum[i] + " ");
}
here is my code for generating random numbers
A fairly easy way to do this is to re-imagine this a little bit. Instead of 'generate a random number', think about a deck of cards. You don't 'generate random cards' - you generate (well, print) 52 cards in a specific order and then you randomize their order. Now you can draw cards off the top of the deck and they'll be random, but they cannot repeat.
Do the same thing: Make a list, fill it with all 42 numbers, then shuffle the list, then pull the top 6 numbers off of the list. Voila: Random - and without repetition.
var numbers = new ArrayList<Integer>();
for (int i = 0; i < 42; i++) numbers.add(i);
Collections.shuffle(numbers);
for (int i = 0; i < 6; i++) {
System.out.print(list.get(i) + " ");
}
Here is a real quick way using streams.
Random r = new Random();
r.ints(n,m) - generate a stream of random values between n and m-1 inclusive
distinct - ensure they are unique
limit(n) - limit to n
toArray - return as an array.
int [] result = r.ints(0,42).distinct().limit(6).toArray();
System.out.println(Arrays.toString(result));
prints something like
[37, 19, 28, 31, 15, 12]
You need to check whether the array contains the newly generated random number. If not, you add it, otherwise, keep generating random numbers until one that's not in the array is generated.
To check whether the number is found in the array, you can write the following function that takes the random integer, your array and returns a boolean:
boolean exists = false;
for (int n : winnum) {
if (n == randomInt) {
exists = true;
break;
}
} return exists;
I have a problem for an online course I am doing. The question is:
Given an Integer x, write a program which generates random numbers between x and 0 until each number in this range has been generated at least once. Once all numbers in this range have been generated, the program should display the numbers which were generated.
I have written a program which I thought would solve this but am having problems with the checking if a number is in the range. Here is my code so far:
public static void main(String[] args) {
Random generator = new Random();
ArrayList<Integer> range = new ArrayList<Integer>();
ArrayList<Integer> generated = new ArrayList<Integer>();
int x = 10;
int count = 0;
for(int i = 0; i<x+1; i++){
range.add(i);
}
while(range.isEmpty() != true){
int temp = generator.nextInt(x-1);
count++;
generated.add(temp);
if(range.contains(temp)){
range.remove(temp);
}
}
}
}
My idea was to first create two arraylists. The first would hold all numbers between 0 and the given x. The second would contain the random numbers generated. I then fill the range arraylist with the range between 0 and x. My While loop then checks this range list to see if it is empty. If not, it generates a random number, adds it to my second arraylist. I then check if this number is in the range arraylist - if it is it removes it and carries on. The problem I am having is it is running into IndexOutOfBoundsException after a few goes. I think this is because I am removing the generated numbers from the arraylist. Can anyone help me with fixing this
EDIT: I cant use any collections or other APIs. This part of the course is mainly about using Arrays and loops etc, not advanced Java stuff.
remove is an overloaded method, there is remove(int) which removes the item at the index specified and there is remove(T) which removes the first object int the list that is equal to the argument you passed in
since you passed an int to the method not an Integer, the first method is chosen
the simpliest modification to your code is replacing range.remove(temp); with range.remove(range.indexOf(temp)); or range.remove((Integer)temp)
also you have to call generator.nextInt(x+1); or else the program will be stuck in an infinite loop
You can just replace range.remove(temp); with range.removeIf(t -> t == temp);
Random generator = new Random();
ArrayList<Integer> range = new ArrayList<Integer>();
ArrayList<Integer> generated = new ArrayList<Integer>();
int x = 10;
int count = 0;
for(int i = 0; i<x+1; i++){
range.add(i);
}
while(range.isEmpty() != true){
int temp = generator.nextInt(x-1);
count++;
generated.add(temp);
if(range.contains(temp)){
range.removeIf(t -> t == temp);
}
}
OR You can use Iterator to remove from the List
for (Iterator<Integer> it = range.iterator(); it.hasNext(); ) {
Integer obj= it.next();
if (obj == temp) {
// Remove the current element from the iterator and the list.
it.remove();
break;
}
}
One more issue in your logic
int temp = generator.nextInt(x-1); The random number you are generating doesn't contain all the numbers. It should be int temp = generator.nextInt(x+2);
Hope the below will meet your requirement.
Random random = new Random();
int x = 3;
List<Integer> range = new ArrayList<>();
for(int i = 0; i <x+1; i++) {
range.add(i);
}
List<Integer> list = new ArrayList<>();
while (!list.containsAll(range)) {
list.add(random.nextInt(x + 1));
}
System.out.println(list);
I want to get n unique random elements from my array.
For example:
if n = 4;
I want to randomly get
array[0], array[3], array[7], array[2]
The problem is getting a random integer will lead to collisions easily (psuedocode):
for n times
{
r = generateRandomInteger within n-1
list.push(array[r]); //array[r] can be the same.
}
collisions abound, especially on small arrays.
What's a particularly elegant way to solve this?
You can use a Set instead of a List which will eliminate the duplicates. Accordingly you'll need to change your loop condition as well. Something like this
while set.size() is less than n
{
r = generateRandomInteger within n-1
set.add(array[r]); //if its the same, it won't be added to the set and the size won't increase
}
You can do this two way : i suggest you to use first one .
First by using SET :
for n times
{
r = generateRandomInteger within n-1
// you can use SET instead of LIST cause SET not allow duplication.
set.push(array[r]); //array[r] can be the same.
}
Second by using LIST :
for n times
{
r = generateRandomInteger within n-1
if(!list.contains(array[r]))
list.push(array[r]); //array[r] can be the same.
}
You can add all random ints to a list and generate a new random, till the list doesnt contains this random int. Thats not the best performance, but it works.
List<Integer> randoms = new ArrayList<Integer>()
for(int i=0; i<n;i++){
while(randoms.contains(r)) {
r = Random.nextInt(array.length-1);
}
randoms.add(r);
list.push(array[r]);
}
Using a Set is probably the best thing to do.
If you want unique elements from array (i.e. the values of array[]) then use R.J's solution. If you want unique indices:
while set.size() is less than n
{
r = generateRandomInteger within n-1
set.add(r);
}
foreach(r: set)
{
list.add(array[r]);
}
Be carefull if you want more elements then the length of the array, since you will get an infinite loop:
if(n>array.length)
{
print("Cannot get more then ... elements!");
return null;
}
int n = 4;
for (int i = 0; i < n; i++)
{
int index = RandomBetweenInclusive(i, array.length() - 1); //made up function
int temp = array[i];
array[i] = array[index];
array[index] = array[i];
}
//array values between indices 0 and n-1 will be random and unique values of array
What I usually do in this scenario is push all the items I want to select-from into a collection
var selectFrom = original.clone; // or build array
var selected = new collection;
Then I go about removing random elements in the selectFrom collection
for (i = 0; i < toSelect; i++)
{
var rndItem = selectFrom[ rand() * selectFrom.length ];
selected.add(rndItem);
selectFrom.remove(rndItem);
}
This way I select randomly from what remains and do not have to worry about clashes in random numbers / indexs.
This question already has answers here:
Random Number Generator: mainly how to stop repetition of numbers. Java
(6 answers)
Closed 9 years ago.
Ok so the objective is to generate 6 random numbers per line/row. With x number of rows (set by the user via UserInput). Each row MUST have unique numbers (non-duplicated numbers). I'm pretty sure the numbers are unique, however I can't seem to get it to have multiple rows, and I cannot figure out for the life of me what part is preventing multiple rows.
package rtg;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class Array {
public static void main(String[] args) {
String name;
int noTickets;
int[] numbers = new int[6];
Set<Integer> randomNumbers = new HashSet<>();
Random rand = new Random();
int ticketCount = 1;
System.out.println("Please input your name");
name = UserInput.readString();
System.out.println("Please input the number of tickets you want");
noTickets = UserInput.readInt();
System.out.println("___________________________________________\n___________________________________________");
System.out.println("___________________________________________\n___________________________________________");
System.out.println("Name: " +name+ "\nNumber of Tickets: " +noTickets+ "\nNumbers: ");
for (ticketCount = 1; ticketCount <= noTickets; ++ticketCount){
while (randomNumbers.size() < 6) {
randomNumbers.add(rand.nextInt(50) + 1);
}
int i = 0;
for (Integer n : randomNumbers) {
numbers[i++] = n;
}
System.out.print( Arrays.toString(numbers) + "\n");
}
}
}
EDIT Thanks a lot everyone, I finally got there, turns out I put the array in the wrong place (it was outside the for loop so only made 1 set of random numbers) Fixed it now. Next challange; having a comparison program to scan 90+ sets of 6 unique numbers, and comparing if any of them match a different set (per row/set >.<)
You can stuff random integers into a Set<Integer> until it has six elements:
Set<Integer> randomNumbers = new HashSet<>();
Random rand = new Random();
while (randomNumbers.size() < 6) {
randomNumbers.add(rand.nextInt(50) + 1);
}
Alternatively, you can generate the numbers 1-50, shuffle them, and pick any six elements:
List<Integer> numbers = new ArrayList<>(50); // known capacity
for (int i = 1; i <= 50; ++i) { numbers.add(i); }
Collections.shuffle(numbers);
List<Integer> sixRandomNumbers = numbers.subList(0, 6);
The first solution does extra work whenever there is a collision; this extra work goes up the greater the ratio is of desired to total numbers. The second does extra work by having to deal with all 50 numbers; the extra work goes down the greater the ratio is of desired to total numbers. It's an interesting question where the cross-over point is.
EDIT (Responding to the edit to the original question) After you use one of the above methods to generate six distinct, random numbers, you need to put them into the variables you are going to use. One way (say, using the first method) is as follows:
int[] numbers = new int[6];
Set<Integer> randomNumbers = new HashSet<>();
Random rand = new Random();
while (randomNumbers.size() < 6) {
randomNumbers.add(rand.nextInt(50) + 1);
}
System.out.println("Six random numbers: " + randomNumbers.toString());
// if you need them as an `int` array:
int i = 0;
for (Integer n : randomNumbers) {
numbers[i++] = n;
}
The numbers array replaces your variables number1, ..., number6.
Use a data type which allows you to check if the int has already been created. For example, adding them to an ArrayList<Integer>.
ArrayList<Integer> numbers = new ArrayList<Integer>();
while(numbers.size() < 6) {
int num = rand.nextInt(50) + 1;
if(!numbers.contains(num)) {
numbers.add(num);
}
}
Of course, as #sanbhat says in the comments, you can use a Set<Integer> and avoid the if() conditional entirely in the loop. However I thought this would be more intuitive for a beginner who doesn't know that the Set API will not add a duplicate element.
Save a sorted list or more efficiently a set of the previously chosen values and check your current selection against the previous ones, if it was previously chosen try again.
If you know the valid range of your random numbers and if the size of that range is not prohibitive, one simple algorithm would be as follows:
Create an array with a size equal to your number range
Consecutively fill your array with the numbers in your number range
Iterate through the list an arbitrarily large number of times; generate two pseudorandom numbers that are within your array indices, and swap the two elements at those indices
After the iteration is complete, you will have an array of uniquely represented numbers that are all within your number range that appear in a random order. This nearly exactly simulates what happens when one shuffles a deck of cards.
You can then write a simple method to consecutively pop numbers out of your array each time it is called.
An advantage of this algorithm is that it can be implemented as an array of primitives, eg. int[], without any need for the Java Collections API.
I'm trying to get random numbers 0 - 499 in sets of 2 based on what the user inputs. For example 234 and 58, and thats one set, but the user may prompt that they wan 8 sets. Im trying to make sure that a redundant number doesnt show up, like 234 & 58, 12 & 444, 198 & 58. (58 showed up twice.)
The way im trying to prevent this is by putting the found numbers into an array and when i go around the next match im checking in the array to make sure they havent been used yet. Was just wondering what the best way of this would be. Like obviously on the first go around no numbers have been chosen yet so i dont need to check. but then the next go around what if i get a redundant? i will get numbers and then check the array, and if it is already in the array how do i go back and get new numbers? a do while loop maybe?
here is what im doing:
//now add the specified number of random connections
System.out.println();
System.out.println("new connection(s): ");
//array for keeping track of the new connections to prevent redundant add's
int redundant [] = new int[con*2];
for( int i = 1; i <= con; i++ ){
Random ran = new Random();
if( i == 1){
int ran1 = ran.nextInt(sWorld.length-1) + 1;
int ran2 = ran.nextInt(sWorld.length-1) + 1;
redundant[i - 1] = ran1;
redundant[i] = ran2;
System.out.println(" " + ran1 + " - " + ran2);
}
else{
int ran1 = ran.nextInt(sWorld.length-1) + 1;
int ran2 = ran.nextInt(sWorld.length-1) + 1;
//need help
}
thanks in advance!
EDIT. Going with a maethod below (using collections)
List<Integer> nums = new LinkedList<Integer>();
for( int i = 0; i <= 499; i++ ){
nums.add(i);
}
//shuffle the collection for more randomness
System.out.println();
System.out.println("new connection(s): ");
for (int x = 1; x <= con; x++){
Collections.shuffle(nums);
Random ran = new Random();
int r1 = nums.remove(ran.nextInt(nums));
int r2 = nums.remove(ran.nextInt(nums));
but having trouble getting the random numbers, any help?
Just fill a collection with all indices in the desired range (i.e. 0 to 499), and then use Collections.shuffle().
One way is to create a list of number from 0-499
List<Integer> nums = new LinkedList<Integer>();
for(int i=0; i<=499; i++) nums.add(i);
Then shuffle the the list
Collections.shuffle(nums);
Then each time you need a non-recurring random number between 0-499, just remove an element from the list
int x = nums.remove()
Use a while cycle and use an array. While your index is not out of scope generate two numbers. Add them to the array if they are not redundant and increase your index accordingly. If they are redundant, do nothing, the next iteration of the while cycle will generate two new numbers anyway.