Why won't this create multiple sets of random numbers? [duplicate] - java

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.

Related

How to make random non-repeating numbers?

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;

Refining a random number generator for Sudoku [duplicate]

This question already has answers here:
Creating random numbers with no duplicates
(20 answers)
Closed 8 years ago.
I'm working on building one of my fist apps and I'm building a Sudoku mobile game. I've built the random number generator I just cant figure out how to write it so that it only generates numbers between 1-9 (not zero) and each of numbers are only generated once. Here is what I have so far:
package randomNumber;
import java.util.Random;
public class OneToNine {
public static final void main(String... aArgs) {
log ("generating random integers in range 1-9");
Random randomGenerator = new Random();
for (int idx = 1; idx <= 9; ++idx) {
int randomInt = randomGenerator.nextInt(9);
log ("Generated : " + randomInt);
}
log("Done. ");
}
private static void log (String aMessage) {
System.out.println(aMessage);
}
}
Rather than worry about generating the numbers in a random order, you should adjust your approach to shuffling the numbers. You know you will have the numbers 1-9 so do something like this:
public ArrayList<Integer> getRandomOrderedNums(){
ArrayList<Integer> numbers = new ArrayList<Integer>();
for(Integer i = 1; i < 10; i++){
numbers.add(i);
}
Collections.shuffle(numbers);
}
For your second part, to see if the numbers are repeated, you can easily use a data structure such as a HashSet, which is the most efficient to check for repeated values. Let me know if you're not fully comfortable with them. Using the hashset, you can come up with a random number, and check if the set contains this number, and if it does, try again.
With regards to the random number, you can just do randomGenerator.nextInt(9) + 1 so it'll always be from 1-9 (inclusive).
You might want to use a function like this:
public static int getRandInt(int max, int min) {
return new Random().nextInt((max - min) + 1) + min;
}

random numbers previously established (java)

The following code shows 4 int variables:
int xy1 = 724329;
int xy2 = 714385;
int xy3 = 715440;
int xy4 = 696492;
I'm pretending to code an app that, by opening it, shows one of those numbers (NOT numbers between them) on java console, randomly. I know that Math.Random class can be used to solve these kind of issues, but I don't know what is the proper way to do so.
So, thanks.
Well it sounds like you just want a collection of possible values, and an index between 0 and 3 inclusive:
int[] values = { 724329, 714385, 715440, 696492 };
Random random = new Random(); // Ideally initialize once for the entire app
int index = random.nextInt(4);
int value = values[index];
Place them into an array and use Random to select a number between 0-3 and use it as a key to select the value from the array.
Try this one.
This line
r.nextInt(nums.length)
selects an integer from 0 to nums.length-1.
Then I print out the randomly selected number from the nums array.
I repeat this 20 times just for demonstration purposes.
import java.util.Random;
public class Test015 {
public static void main(String[] args) {
int[] nums = {724329, 714385, 715440, 696492};
Random r = new Random();
for (int i=0; i<20; i++){
int index = r.nextInt(nums.length);
System.out.println("Number randomly chosen: " + nums[index]);
}
}
}

random unique number in java

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.

Generate non repeating random number within range in Java

I want to generate random numbers within the range 1 to 4, 4 including.
Here is my code:
int num = r.nextInt(4) + 1; //r is instance of Random.
However, I am running the above code in a loop and don't want repeating random number.
What happens now is often I am getting:
1,1,1,2,3,1,4,2,2,1,4,2,4,4,2,1,4,3,3,1,4,2,4,1 as my output.
Here, though the numbers are random within the range(1-4), but often repeated like the number "1"in the first 3 iterations.
What I am looking for is a way to get non repeating random number within the loop.
One simple way I know is of keeping the last random number before current iteration and compare, but I am sure there must be better solution to this.
Thanks in advance.
Use random.nextInt(range-1) and then map that number to the output number with a function that excludes the previous number:
public class Test {
private final Random random = new Random();
private final int range;
private int previous;
Test(int range) { this.range = range; }
int nextRnd() {
if (previous == 0) return previous = random.nextInt(range) + 1;
final int rnd = random.nextInt(range-1) + 1;
return previous = (rnd < previous? rnd : rnd + 1);
}
public static void main(String[] args) {
final Test t = new Test(4);
for (int i = 0; i < 100; i++) System.out.println(t.nextRnd());
}
}
There is no "better" answer.
You are getting a random number. Check this line:
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
this could be perfectly random.
So I propose you describe a better requirement.
Do you want always a next number that is different from the previous? Do you want a maximum of duplicates in a special rang? lets say within 6 consecutive numbers, every number is allowed to occur twice?
If you bring such a requirement we might be able to help you. otherwise we can just say: what you seeing is really random :)
As you have more numbers than you have to choice from you have to repeat some numbers. All you can do is minimise the number of immediate repeats.
One way to do this is to use Collections.shuffle which allow you to have numbers in a random order, without repeats and do this each time. You could prevent the last N value being repeated.
To stop consecutive repeating numbers you can reduce the range and use modulus.
int n = 0, max = 4;
Random rand = new Random();
for(int i = 0; i < numbers; i++) {
n = (n + rand.nextInt(max-1)) % max;
int numToUse = n + 1;
// use this number.
}
This work as there is really only max-1 possible values as you are excluding the last value used.
Here is an algorithm:
initialize an array A[4] with the numbers 1-4
set a counter Acnt, the effective size of A. Initialize to 4
for i in 1 to length(output sequence)
choose a random integer X from 0 to Acnt -1
save A[X] to your output sequence
swap(A[X],A[Acnt - 1])
Acnt--
if(Acnt == 0) Acnt = lengh(A)
Imagine A is a bag of balls with the numbers 1-4. Each iteration of your loop, you remove a ball. Rather than actually deleting from the array, which is expenisve, you simply hide the ball at the end of the array. When you decrement the number of balls in the bag (Acnt), the next ball you select comes from the non-hidden balls.
When you have no more balls to select, you unhide the balls by resetting the count of balls in your bag back to the full count.
This is basically the standard shuffle algorithm.
Edit: Rereading the question, I see now he allows repeats after only 1 number instead of the whole sequence, in which case it all you need to do to modify this is change if (Acnt == 0) to if(Acnt == length(A) - 1).

Categories