Random number generator generates duplicates - java

Framework: Java
public static List<Integer> buttonIdList = new ArrayList();
public void myMainMethod() {
for(Integer i = 0; i < 11; i++) {
int randomButtonId = getUniqueIdNumber();
}
}
private static Integer getUniqueIdNumber() {
Random ran = new Random();
int randomButtonId = ran.nextInt(20) + 1;
if(buttonIdList.contains(randomButtonId)) {
getUniqueIdNumber();
} else {
buttonIdList.add(randomButtonId);
}
return randomButtonId;
}
When the code encounters a duplicate, it calls itself (recursively) and in the second try if the number is unique the return statement returns it to the myMainMethod or to getUniqueIdNUmber?
Where should the return statement be placed?

You should return the result of the recursive call:
private static Integer getUniqueIdNumber() {
Random ran = new Random();
int randomButtonId = ran.nextInt(20) + 1;
if(buttonIdList.contains(randomButtonId)) {
return getUniqueIdNumber();
} else {
buttonIdList.add(randomButtonId);
}
return randomButtonId;
}
P.S., it would be better to make Random ran a static variable instead of creating a new Random instance in each recursive call.
private static Random ran = new Random();
private static Integer getUniqueIdNumber() {
int randomButtonId = ran.nextInt(20) + 1;
if(buttonIdList.contains(randomButtonId)) {
return getUniqueIdNumber();
} else {
buttonIdList.add(randomButtonId);
return randomButtonId;
}
}
And you might consider changing buttonIdList to a HashSet (or LinkedHashSet if you care about insertion order) in order to make the search for existing number more efficient.

Related

Randomly take an int element from an integer array

I have an Integer array and I want to randomly take an element from those who are not null. I have tried this but after the else, I cannot use return because the method is int. But I don't know what to write after else in order to return at the beginning and take a new random element.
public int getRandomPosition(){
Random x = new Random();
int b = x.nextInt(2*number0fCardPairs);
if (myArray[b] != null){
return b;
}
else{
return;
}
}
You could make your method recursive:
private Random x = new Random();
public int getRandomPosition(){
int b = x.nextInt(sizeOfArray);
if (myArray[b] != null){
return b;
}
// else {
return getRandomPosition();
}
or using a while-loop
private Random x = new Random();
public int getRandomPosition(){
Integer result = null;
do {
int index = x.nextInt(sizeOfArray);
result = myArray[index];
} while (result == null);
return result.intValue();
}
Theoretically, however, the method could run indefinitely if you're really unlucky. Therefore, it probably makes sense to include a counter, so for example only try max. 20 times, then return null:
private Random x = new Random();
public int getRandomPosition(){
Integer result = null;
int tries = 0;
do {
int index = x.nextInt(sizeOfArray);
result = myArray[index];
} while (result == null && ++tries < 20);
return result.intValue();
}
You can achieve this by using a loop.
public int getRandomPosition(){
Random random = new Random();
int randomIdx = random.nextInt(array.length);
// while array at randomIdx is null, continue getting new randomIdx
while (array[randomIdx] == null) {
randomIdx = random.nextInt(array.length);
}
return randomIdx;
}
Note that if all the elements inside the array are null, it will be an infinite loop. Hope you find this helpful!
You can do:
Integer[] myArray = {1,2,3,null,5};
List<Integer> nonNullIntegers = Arrays.stream(myArray)
.filter(Objects::nonNull)
.collect(Collectors.toList());
Random random = new Random();
Integer randomInteger = nonNullIntegers.get(random.nextInt(nonNullIntegers.size()));

How can I produce unique values of Object via Random Process in Java

I want to produce unique values of Movie Object via Random. I wrote a code snippet but I'm not sure all values cannot be unique by using Random().
How can I do this process to produce all of these unique values?
Here is my code snippets shown below.
private static ArrayList<Movie> addMovies(ArrayList<Movie> movieList) {
for(int i=0;i<20;i++) {
Movie movie = new Movie();
movie.setId(defineMovieId());
movie.setTitle(defineMovieName(15));
movieList.add(movie);
}
return movieList;
}
public static String defineMovieName(int n) {
// chose a Character random from this String
String AlphaNumericString = "ABCÇDEFGHIİJKLMNOÖPQRSŞTUÜVWXYZ"
+ "abcçdefghıijklmnoöpqrsştuüvxyz";
StringBuilder sb = new StringBuilder(n);
for (int i = 0; i < n; i++) {
int index
= (int)(AlphaNumericString.length()
* Math.random());
sb.append(AlphaNumericString
.charAt(index));
}
return sb.toString();
}
public static long defineMovieId() {
int max = 1000;
int min = 1;
int range = max - min + 1;
int res = (int) ( Math.random()*range) + min;
return res;
}
The methods which you have defined do not guarantee random IDs or random names. For guaranteed unique values, you can do the following:
For unique ID: create a static variable of AtomicLong type and use getAndIncrement()
For unique names: use UUID.randomUUID()
Demo:
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
public class Main {
static final long INITIAL_VALUE = 1000000;
static AtomicLong atomicLong = new AtomicLong(INITIAL_VALUE);
public static void main(String[] args) {
// Tests
System.out.println("10 random IDs:");
for (int i = 1; i <= 10; i++) {
System.out.print(defineMovieId() + " ");
}
System.out.println();
System.out.println("10 random movie names:");
for (int i = 1; i <= 10; i++) {
System.out.print(defineMovieName() + " ");
}
}
public static long defineMovieId() {
return atomicLong.getAndIncrement();
}
public static String defineMovieName() {
return UUID.randomUUID().toString().replace("-", "");
}
}
Output:
10 random IDs:
1000000 1000001 1000002 1000003 1000004 1000005 1000006 1000007 1000008 1000009
10 random movie names:
0c77d209fb624415af7100c3184b35a6 1262e50b680f4a738a607ff757f2b510 7b93c73d93b34db88fc99d1096c1ce84 cbb9c6c90fb8489dbd9c52d4ebdc2ca3 9ba1d409b32b4c55a7562d714aadc220 ec40b647f33a4fc6becc8c5741eb8bf7 c1fbb7bb77d1417c86c2064039f62dec 82b52fdae1d24602b5ee9becd73ba3ce 2d82d481282b4684b55c168e9d216f36 27b02bf63b054d32a0e43992a5fcb124
Random is not generate a series of unique numbers, just if get lucky.
Better use a static int field for id and increase it each time you need a new id.
//classes names are obvious fake since there are not any random involved, just an example
public class TestRandom {
static int id=0;
public static void main(String[] args)
{
TestRandom tr = new TestRandom();
RandomIdObj ro1 = tr.new RandomIdObj(tr.getNextId(),"obj_1");
RandomIdObj ro2 = tr.new RandomIdObj(tr.getNextId(),"obj_2");
System.out.println(ro1);
System.out.println(ro2);
}
public int getNextId()
{
return ++id;
}
class RandomIdObj
{
int id;
String name;
RandomIdObj(int id,String name)
{
this.id =id;
this.name = name;
}
public String toString()
{
return this.id+":"+this.name;
}
}
}
Output:
[unique_id,obj_name]
1:obj_1
2:obj_2

Exchange variable in non specified method

Im a newcomer :)
However, my program has a table and a RandomGen should get the highest random int by getRowCount -> checkvar1.
Now, the main class gets checkvar1 and sends it to setVariable(), then I want to exchange this checkvar1 with randomGen to limit the maximum generated integer.
So this of course doesn't work because the parameters in randomGen() aren't set and I cannot set them, because then the exchange to the onActionPerformed() method in my main class doesn't work anymore.
public final class RandomGen
{
// EXCHANGE OF CHECKVAR1 FOR RANDOM GEN
public static void setVariable(int checkvar1)
{
System.out.print(checkvar1);
}
// RANDOM GENERATOR
public static int randomGen()
{
Random rand = new Random();
int var1 = rand.nextInt(checkvar1) + 1;
return var1;
}
}
Here my main class:
public void onActionPerformed(java.awt.event.ActionEvent evt) {
//NUMBER OF LAST ROW
int checkvar1 = (Integer)jTable1.getRowCount();
//->EXCHANGE WITH setVariable()
RandomGen.setVariable(checkvar1);
if (checkvar1 >= 3) {
int recogvar1 = checkvar1 - 1;
Object checkobj1 = jTable1.getModel().getValueAt(recogvar1, 0);
if (checkobj1 == null){
//...
}
else {
int var1 = RandomGen.variable();
String result = var1 + "";
jTextField1.setText(result);
//System.out.print(result);
}
}
else {
String rule2 = "At least " + 3 + " rows should be filled";
jTextField1.setText(rule2);
}
You are doing nothing with your setVariable in your class RandomGen. So You only need to change this.
// RANDOM GENERATOR
public static int randomGen(int checkvar1)
{
Random rand = new Random();
int var1 = rand.nextInt(checkvar1) + 1;
return var1;
}
And in your main Method try this.
//NUMBER OF LAST ROW
int checkvar1 = (Integer)jTable1.getRowCount();
//->EXCHANGE WITH randomGenerator
checkvar1 = RandomGen.randomGen(checkvar1);

pseudo-random for index on an infinite strip

I want to create a class that represents an infinite (2^32 can be considered as infinite) strip on which there are pseudo-random numbers. The interface should be very simple; the constructor should get an instance of Random; and there should be a method to get the random number for an index.
Note that I don't want to store a huge lookup table and precalculate it; I want it to be done on the fly.
public class InfiniteRandomStrip {
public InfiniteRandomStrip(Random r) {
...
}
public int getNumber(int index) {
// magic code here
}
}
Note that the code should pass the following test:
Random seed = new Random(123);
Random seed2 = new Random(123);
InfiniteRandomStrip strip = new InfiniteRandomStrip(seed);
InfiniteRandomStrip strip2 = new InfiniteRandomStrip(seed2);
int first = strip.getNumber(454); // consume the random
if(strip.getNumber(5) == strip2.getNumber(5) )
System.out.println("TEST1 OK");
if(first == strip.getNumber(454) )
System.out.println("TEST2 OK");
I've had no luck finding any example or algorithm for such a random list case. If such a problem has no solution, I will be glad to hear an explanation why.
You could clone the Random object in the getNumber method so that you start at the same seed each time. Then compute nextInt repeatedly until you get to the correct index.
int getNumber(int index) {
Random r = this.seed.clone();
for (int i = 0; i < index - 1; ++i) {
r.nextInt();
}
return r.nextInt();
}
public class InfiniteRandomStrip {
private final long seed;
public InfiniteRandomStrip(Random r) {
this.seed = r.nextLong();
}
public int getNumber(int index) {
return new Random(seed ^ index).nextInt();
}
}

Finding duplicate random numbers in an ArrayList

public class LotteryNumbers {
private ArrayList <Integer> numbers;
public LotteryNumbers() {
this.numbers = new ArrayList <Integer> ();
this.drawNumbers();
}
public ArrayList <Integer> numbers() {
return this.numbers;
}
public void drawNumbers() {
Random random = new Random ();
int counter = 0;
while (counter < 7) {
this.numbers.add(random.nextInt(39) + 1);
counter++;
}
}
This is a class used for printing 7 numbers from 1..39.
It does that job but the problem is I want the 7 random numbers to be different.
How do I check if an arrayList contains the same number since it is random?
Thanks for reading.
You could try using the contains() method from the ArrayList numbers:
public void drawNumbers()
{
Random random = new Random();
int counter = 0;
int choice;
while (counter < 7) {
choice = random.nextInt(39) + 1;
if (numbers.contains(choice)) {
continue;
}
numbers.add(choice);
counter++;
}
}
From Java Docs:
public boolean contains(Object o): Returns true if this list contains
the specified element.
So, if the ArrayList already contains the choice (randomly generated), it will continue to the next iteration (counter won't be increased) and choose another random number. If it doesn't contains the choice, it will add it to the array and increase counter.
This can also be done by this way (without using continue)
if (!numbers.contains(choice)) {
numbers.add(choice);
counter++;
}
How do I check if an ArrayList contains the same number since it is random?
Like this (example):
public void drawNumbers() {
Random random = new Random ();
int counter = 0;
while (counter < 7) {
int newNumber = random.nextInt(39) + 1;
if (! numbers.contains(newNumber)) {
this.numbers.add(newNumber);
counter++;
}
}
}
You could use contains as as the earlier responses suggest, however contains on an array list in inefficient with O(n) complexity. One of the comments by #TheLostMind suggest using a Set, the best Set implementation to use in this instance is BitSet, note it does not confirm to the java.util.Set interface specification.
public class LotteryNumbers {
private final int[] numbers = new int[7]
public LotteryNumbers() {
this.drawNumbers();
}
public int[] numbers() {
return this.numbers;
}
public void drawNumbers() {
BitSet selected = new BitSet(40);
Random random = new Random ();
int counter = 0;
while (counter < 7) {
int num = random.nextInt(39) + 1;
if(!selected.get(num)) {
selected.flip(num);
numbers[counter++] = num;
}
}
}
This implementation, tho unlikely, does not guarantee that you will always get a result.
You could also put your numbers in a list and use COllections.shuffle and get the first 7 occurences.
You do not need to check if duplicate...
ArrayList list = new ArrayList();
list.add(1);
list.add(2);
....
Collections.shuffle(list);
loop and get your numbers...
int num = Integer.intValue(list.get(i));

Categories