Random number generator without repetition Class in Java - java

First of all, I'm a newbie Android App developer. In my App I need a class which generates random numbers in a given range avoiding repetition. I've searched much for this issue, but I haven't found any concrete solution for my case. Well, thought I found one which I slightly readapt, but it's not working fine. The code is the following one:
public class NoRepeatRandom {
private int[] number = null;
private int N = -1;
private int size = 0;
public NoRepeatRandom(int minVal, int maxVal)
{
N = (maxVal - minVal) + 1;
number = new int[N];
int n = minVal;
for(int i = 0; i < N; i++)
number[i] = n++;
size = N;
}
public void Reset() { size = N; }
// Returns -1 if none left
public int GetRandom()
{
if(size <= 0) return -1;
int index = size * (int)Math.random();
int randNum = number[index];
// Swap current value with current last, so we don't actually
// have to remove anything, and our list still contains everything
// if we want to reset
number[index] = number[size-1];
number[--size] = randNum;
return randNum;
}
}
When I call GetRandom() I don't achieve the expected result, because it always returns the minimum number of the range given. For example:
NoRepeatRandom nrr = new NoRepeatRandom(0, 10);
int yes = nrr.GetRandom();
//Here I create a Toast just to see the numbers that the method is returning.
Toast toast = Toast.makeText(MainActivity.this, Integer.toString(yes), Toast.LENGTH_SHORT);
toast.show();
And the result is: 0,0,0,0,0,0....
For range (5,10) the result is 5,5,5,5....
Does anybody knows what is wrong with the code? I would really appreciate any help!
Thank you in advance.

I guess this line is issue.
int index = size * (int) Math.random();
This evaluates to Zero always.
Edit:
Just consolidating comments from Jeroen Vannevel and OP.
Math.random() will return a value between 0.0 and 1.0, which when cast with (int) will always evaluates to ZERO. You ca use as below.
int index = (int) (size * Math.random());

You should try using Random class:
http://developer.android.com/reference/java/util/Random.html
Random random = new Random();
int randomNo = random.nextInt(10); // 0 to 9

Related

Random numbers in an array without duplicates

I know this question has been answered out there, but those solutions don't fit in with the way I'm going about, so I'm enquiring to see if there is a simpler solution.
I'm using the set interface and I need there to be 6 random numbers and you can't have duplicates in the set interface.
This is what I've currently got, the way I I'm doing it is not ideal and often causes crashes.
public void drawLotto(){ //The validation I have here I know isn't the most effective way and is-
Random r = new Random();//resource comsuning but this was the only way I could think of doing it.
int draw[] = new int[6];
int min = 1;
for(int i = 0; i < draw.length; i++){
draw[i] = r.nextInt(lotteryMax-min) + min;
lotteryDraw.add(draw[i]);
}
int size = lotteryDraw.size();
if(size != 6){
drawLotto();
}
for(int i = 0; i < draw.length; i++){
System.out.println(draw[i] + " ,");
}
System.out.println();
}
``
Thank you, any help is appreciated.
The reason you have problems is because you recursively call drawLotto(), which will in turn create a new instance of the Random. If drawLotto() cannot create a correct list, it will have to do a full retry of all 6 numbers. This might cause your application to use a high amount of memory, resulting in the crash you experience
One way you could do this is by keep looping until you find 6 unique numbers:
public void drawLotto(){
Random r = new Random();
Set<Integer> draw = new HashSet<>();
int min = 1;
int lotteryMax = 50;
while(draw.size() < 6){
draw.add(r.nextInt(lotteryMax-min) + min);
}
String lotteryDrawing = draw.stream().map(String::valueOf).collect(Collectors.joining(" ,"));
System.out.println(lotteryDrawing);
}
Though you have to make sure that your lotteryMax is higher than the number you need
check this out
public void drawLotto(){
Random random = new Random();
while(lotteryDraw.size()<6) {
lotteryDraw.add(random.nextInt(max-min)+min);
}
lotteryDraw.forEach(System.out::println);
}
Use a set if you want to avoid duplicate values.
Example:
public static Set <Integer> drawLotto() { //The validation I have here I know isn't the most effective way and is-
Random r = new Random(); //resource comsuning but this was the only way I could think of doing it.
int draw[] = new int[6];
int min = 1;
int lotteryMax = 10;
Set<Integer> lotteryDraw = new HashSet<Integer>();
for (int i = 0; i < draw.length; i++) {
draw[i] = r.nextInt(lotteryMax - min) + min;
lotteryDraw.add(draw[i]);
}
int size = lotteryDraw.size();
if (size != 6) {
return drawLotto();
} else {
return lotteryDraw;
}
}

Random array with size, min and max value with short

I'm doing a task where you input 3 parameters which are size, minimum value and maximum value. It then is meant to return a random number between the minimum and maximum value of the size inputted. There are also other validations such as if the min is more than the max which I've already done.
I am able to do the task using integer instead of short. As soon as I change the data type a bunch of errors come.
Below is what I've done so far, it works as expected but I am pretty sure that there is not meant to be a bottom return null, I get errors when I delete it. On the second loop, it should return the array instead of doing a system print line. The other issue is the data types at the top, it should be short maxVal and short minVal instead of int but I can't get it to work with short.
I would very much appreciate all help. Thanks!
public static ArrayList<Short> RandomArray1(int n, int maxVal, int minVal){
if(n <= 0) {
return null;
}
if(minVal > maxVal) {
return new ArrayList<Short>();
}
ArrayList<Integer> ran = new ArrayList<Integer>();
Random rand = new Random();
for(int i = 0; i < n; i++) {
int result = rand.nextInt(maxVal-minVal) + minVal;
//System.out.println(result);
ran.add(result);
}
for (int i = 0; i < ran.size(); i++) {
System.out.println(ran.get(i));
//return (ArrayList<Short>)ran.get(i);
}
return null;
I would do it like this.
first, method names by convention should start with lower case letters.
Use the method to generate the values and return the list
return interface types as opposed to implementation types (e.g. List)
throw exceptions if the arguments don't satisfy the requirements.
Note, having to cast the arguments to shorts is cumbersome but it prevents errors at compile time. Otherwise you may want to throw an additional run time exception if the values aren't within Short.MIN_VALUE and Short.MAX_VALUE.
public class RandomShorts {
public static void main(String[] args) {
List<Short> shortList = randomList(20, (short)200, (short)99);
shortList.forEach(System.out::println);
}
public static List<Short> randomList(short n, short maxVal,
short minVal) {
if (n <= 0 || minVal >= maxVal) {
throw new IllegalArgumentException(
"\nn must be > 0\nminVal must be < maxVal\n");
}
List<Short> ran = new ArrayList<>();
Random rand = new Random();
for (int i = 0; i < n; i++) {
short result =
(short) (rand.nextInt(maxVal - minVal) + minVal);
ran.add(result);
}
return ran;
}
}
If you just want to return a single random number using the supplied arguments, they you can do it like this.
public static short randomShort(int n, short maxVal, short minVal) {
return (short)((Math.random()*(maxVal - minVal))+minVal);
}
For adding the short to random list since there is not Random.nextShort(), you'll have to substitute the line
int result = rand.nextInt(maxVal-minVal) + minVal;
for
short result = (short) (rand.nextInt(maxVal-minVal) + minVal);
Where then you can add to your ran array instead of the second for loop returning the ArrayList as a short
public static short[] generateRandomShortArray (int sampleSize, short min, short max) {
short[] result = new short[sampleSize];
for (int index = 0; index < result.length; index++) {
result[index] = (short)((Math.random() * (max-min)) + min);
}
return result;
}
If an array list is required just return Arrays.asList(result);

What is wrong with this simple application of binary addition algorithm in Java?

I am trying to apply a simple binary addition algorithm in Java, but I am getting errors repeatedly. Could anyone please help me. Thanks!
public class BasicBinaryAddition {
public static void main(String[] args)
{
int []sum = new int [3];
int []a = {0,1,0};
int []b = {1,1,0};
int carry =0;
int bitIndex;
for (bitIndex =0; bitIndex < a.length; bitIndex++)
{
int bitSum = a[bitIndex] + b[bitIndex] + carry;
sum[bitIndex] = bitSum%2;
double d = bitSum/2;
carry = (int) Math.floor(d);
}
sum[bitIndex] = carry;
for (int i = 0 ; i <= sum.length-1; i++)
System.out.print(sum[I]+"");
}
}
Your sum array is too short to hold the full result. Make it length 4, this will avoid the ArrayIndexOutOfBoundsException.
The way you calculate the carry could also be simplified to
carry = bitSum / 2;
This is an integer division and yields an integer result.
Adding two 3-bit numbers could result in 4 bits. So, you should declare
int []sum = new int [4];
Also, you should use small i in the last for-loop
System.out.print(sum[i]+"");
You should put (sum[bitIndex] = carry) inside the loop;
public class BasicBinaryAddition {
public static void main(String[] args)
{
int []sum = new int [3];
int []a = {0,1,0};
int []b = {1,1,0};
int carry =0;
int bitIndex;
for (bitIndex =0; bitIndex < a.length-1; bitIndex++)
{
int bitSum = a[bitIndex] + b[bitIndex] + carry;
sum[bitIndex] = bitSum%2;
double d = bitSum/2;
carry = (int) Math.floor(d);
sum[bitIndex] = carry;
}
for (int i = 0 ; i <= sum.length-1; i++)
System.out.print(sum[I]+"");
}
}
This looks like homework so I will just point you in the right direction.
The first problem is in your line:
System.out.print(sum[I]+"");
You are using "I" instead of "i" so the compiler is upset that it can't find a variable "I".
The second problem is that you have an overflow problem. If you add 2 binary numbers of length 3 it is possible to have an answer that is 4 bits long.
101 + 100 = 1001
When you perform the line: sum[bitIndex] = carry, bit index equals 3, which means the 4th item of the array sum (remember Java arrays start from index 0). However sum is declared to be of length 3, so Java's head explodes in rage that you tried to access an element of an array that is out of bounds. The answer to this problem is to declare sum to be of length 4.
Another thing that can be cleaned up are the lines:
double d = bitSum/2;
carry = (int) Math.floor(d);
This can be simplified to:
carry = bitSum/2;
This works because carry and bitSum are both integers, so Java will perform integer division, which just ignore anything that would happen after the decimal in regular division.

Incorrect return on binary to dec converter

Fixing up and tidying the converter when I noticed that it somehow gives out incorrect conversions.
For example, when creating a new number to convert using BinaryNumber bn1 = new BinaryNumber("1011"); and then asking it to give out a result with System.out.println(bn1.convertToDecimal()); it prints out 3 instead of the correct result of 11.
I'm almost sure I got the actual conversion wrong but going through it in my head I can't find the mistake.
public class BinaryNumber {
private String n;
public BinaryNumber(String pn) {
n = pn;
}
public String getN() {
return n;
}
// Creating the .convertToDecimal()
public int convertToDecimal() {
int bitPosition = 0;
int sum = 0;
for (int i = n.length() - 1; i >= 0; i--) {
sum = sum + (int) Math.pow(2, bitPosition) * (n.charAt(i) - 48);
}
return sum;
}
// Creating the .add to add the two different binary numbers after
// converting
public int add(BinaryNumber bn2) {
return convertToDecimal() + bn2.convertToDecimal();
}
// Creating the .sub to subtract the two different binary numbers after
// converting
public int sub(BinaryNumber bn2) {
return convertToDecimal() - bn2.convertToDecimal();
}
}
You just need to increment your bitposition variable.
int bitPosition = 0;
int sum = 0;
for (int i = n.length() - 1; i >= 0; i--) {
sum = sum + (int) Math.pow(2, bitPosition++) * (n.charAt(i) - 48);
}
return sum;
First of all, Java has a built in binary system, using the primitive int type. You can use this by putting 0b before the number in binary form.
If you are doing this for learning purposes, then here's what's happening:
On each iteration, the value of bitPosition is always 0, because you never update it. Of course, you want to increase it with each iteration. This can be done simply by changing
Math.pow(2, bitPosition)
to
Math.pow(2, bitPosition++)
with the ++ after the variable to change it after it is referenced.

Creating and printing an array of non repeating integers - Java [duplicate]

This question already has answers here:
Java generating non-repeating random numbers
(12 answers)
Closed 9 years ago.
I am trying to write a guessing game program where a 4 digit number is randomly generated. The numbers need to be unique (as in they do not repeat at any time) I am fairly new to Java and I am having trouble displaying the numbers in an array. Also I can't figure out a way to check a number against the others more than once. EX: If random number A is the same as random number B it will make a new random number A. But I dont know how to check if the NEW random A is the same as number B without writing the same code over and over and over. (clearly some kind of loop but I have no idea which kind)
import java.util.Random;
public class Game {
public static void main(String[] args) {
// TODO Auto-generated method stub
int rand1 = 0;
int rand2 = 0;
int rand3 = 0;
int rand4 = 0;
int[] randArray = new int[]{rand1, rand2, rand3, rand4};
Random randy = new Random();
int a = randy.nextInt(9);
int b = randy.nextInt(9);
int c = randy.nextInt(9);
int d = randy.nextInt(9);
//how to check the variable more than one time?
a = rand1;
if (b == a) {
b = randy.nextInt(9);
}
else rand2 = b;
if (c == a || c == b) {
c = randy.nextInt(9);
}
else rand3 = c;
if (d == a || d == b || d == c) {
d = randy.nextInt(9);
}
else rand4 = d;
System.out.print(randArray); //prints gibberish
//prints the numbers fine
//System.out.print(rand1);
//System.out.print(rand2);
//System.out.print(rand3);
//System.out.print(rand4);
}
}
You might first add the random numbers to a java.util.HashSet and then convert it to an array. This way you get rid of all duplicates.
How about using an ArrayList instead?
The syntax is different, but then you can do your program in a looping fashion.
For example:
ArrayList<Integer> randNums = new ArrayList();
while(randNums.size() != 4) {
int a = randy.nextInt(9);
if(false == randNums.contains(a))
randNums.add(a);
}
Edit to add a side note: ArrayList has the prettier printing you are looking for as well.
If you want to change your current array type to Integer instead of an int then i suggest you to take one of the other answers. My first instinct was to show you how clean, readable and simple it will be if you used ArrayList<Integer> and its power and then convert it to Integer[] again no int[].
At the end i decided to wrote you an answer, that may not be the most elegant and defentily not the shortest one, but it will teach you how to think right before you could use tools that will take those element off (ArrayList and its powers as we said).
The algorithm is quite simple.
You create int-array at the n size you needed.
You iterate over it from 0 to n and with every iteration you:
A. Creating a do-while loop that will generate a random number from 0-9.
B. Generate a random temp number from 0-9.
C. Iterating over your current readArray to look-up if the generated number is inside, and if so it will flag it and stop the look-up process (because we found that we already have it).
D. Will check if the flag isExists set as true, if so, then will go into step B again otherwise will go to step 3.
If we reached to the end of look-up(for) without changing flag to true, than the temp(generated number) is not at our current array, and it will be safe to add it.
Will check if we reach to the end of the array or there are more array cell to fill. i < readArray.length.
Code:
Random randy = new Random();
int[] readArray = new int[4];
for (int i = 0; i < readArray.length; i++) {
int temp;
boolean isExists;
do {
isExists = false;
temp = randy.nextInt(10);
for (int j = 0; j < i; j++)
{
if (readArray[j] == temp)
{
isExists = true;
break;
}
}
} while (isExists);
readArray[i] = temp;
}
System.out.println(Arrays.toString(readArray));
If you're OK with storing in memory an 'int' array of 10000 entries:
public class YourClass
{
private static int final SIZE = 10000;
private int[] array = new int[SIZE];
private int currIteration = 0;
private Random random = new Random();
public YourClass()
{
for (int i=0; i<SIZE; i++)
array[i] = i;
}
public int getRandVal()
{
int index = random.nextInt(SIZE-currIteration);
int val = array[index];
array[index] = array[SIZE-currIteration-1];
array[SIZE-currIteration-1] = val;
if (++currIteration == SIZE)
currIteration = 0;
return val;
}
}
For generating random unique integers
Use a Set to create a collection of unique values. Otherwise, for each random number generated, iterate over the array to ensure it's unique before adding it.
Integer[] createGuesses(int numGuesses, int low, int high)
{
Set<Integer> guesses = new HashSet<>();
Random rand = new Random();
while(guesses.size() < numGuesses)
guesses.add(low + rand.nextInt(high - low));
return guesses.toArray(new Integer[numGuesses]);
}

Categories