Limiting duplicate random numbers - java

I just want to know how to limit to number of times a random number appears. I have generated random numbers of 1 to 10 and want to limit each number to appear 4 times.
myArray[i][j] = rand.nextInt(11);
for (int i=0; i < myArray.length; i++) {
for (int j=0; j < myArray[i].length; j++) {
myArray[i][j] = rand.nextInt(11);
System.out.print(" " + myArray[i][j]);
The code above creates the randoms numbers. Just want to limit them.

Since you are limited to 10 * 4 = 40 numbers you can use a list and randomize the index :
List<Integer> numbers = new ArrayList<Integer>();
for (int i = 1; i < 11; ++i) {
for (int j = 0; j < 4; ++j)
numbers.add(i);
}
And then when you assign a random number :
int i = rand.nextInt(numbers.size());
myArray[i][j] = numbers.get(i);
numbers.remove(i);
This assumes your two dimensional will not contain more then 40 numbers

My solution stores the result in arrayList:
public class Example {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
final int range = 10;
int[] numbers = new int[range + 1];
int sum = 0;
final int noOfOccurances = 4;
final int size = range * noOfOccurances;
Arrays.fill(numbers, 0);
Random generator = new Random();
List<Integer> numbersArray = new ArrayList<>();
while (sum != size) {
int randomNumber = generator.nextInt(range) + 1;
if (numbers[randomNumber] != noOfOccurances) {
numbers[randomNumber]++;
sum++;
numbersArray.add(randomNumber);
}
}
System.out.println(numbersArray);
}
}

How about storing the count of the generated int's in an array, or Map, or anything?
Map<Integer, Integer> randomCounts = new HashMap<Integer, Integer>();
... your for loops
myArray[i][j] = rand.nextInt(11);
if (randomCounts.containsKey(myArray[i][j])) {
randomCounts.put(myArray[i][j],randomCounts.get(myArray[i][j])+1);
} else {
randomCounts.put(myArray[i][j],1);
}
And if you want to check them, just iterate through your map, and voilá. :)

You can make a method to check if the generated number exists more than 4 times in the array and create a new random number if it does. It should look like this:
import java.util.Random;
public class rndNumberGenerator {
public static void main (String[] args) {
int[][] myArray = new int[2][5];
Random rand = new Random();
int randomNumber;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 5; j++) {
do {
randomNumber = rand.nextInt(11);
} while(overMax(myArray, randomNumber) == true);
myArray[i][j] = randomNumber;
System.out.print(" " + myArray[i][j]);
}
}
}
public static boolean overMax(int[][] array, int number) {
int max = 4;
int count = 0;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 5; j++) {
if (array[i][j] == number) {
count++;
}
}
}
if (count >= max)
return true;
else
return false;
}
}
Hope this helped you, if you have any other questions feel free to ask.

I take suggestion by pshemek (vote up): instead the ArrayList, I use the Set because it can't contain duplicate numbers and you have'nt to espicitate control.
An implementation: the copy{right, left} is of pshemek, I had only extended the idea:)
public class Example {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
int[] numbers = new int[11];
int sum = 0;
final int range = 10;
final int noOfOccurances = 4;
Arrays.fill(numbers, 0);
Random generator = new Random();
Set<Integer> numbersArray = new TreeSet<Integer>();
while (sum != range * noOfOccurances) {
int randomNumber = generator.nextInt(range) + 1;
sum++;//correction for first comment
numbersArray.add(randomNumber); // randomNumber will never be twice: a Set cointains ever one and only one instance of an determinated element
}
System.out.println(numbersArray);
}
}//end class

You could write your own:
public static class CountedRandom {
// My rng.
Random rand = new Random();
// Keeps track of the counts so far.
Map<Integer, Integer> counts = new HashMap<Integer, Integer>();
// The limit I must apply.
final int limit;
public CountedRandom(int limit) {
this.limit = limit;
}
public int nextInt(int l) {
int r;
do {
// Keep getting a new number until we hit one that has'n been overused.
r = rand.nextInt(l);
} while (count(r) >= limit);
return r;
}
private int count(int r) {
// How many times have we seen this one so far.
Integer counted = counts.get(r);
if ( counted == null ) {
// Never!
counted = new Integer(0);
}
// Remember the new value.
counts.put(r, counted + 1);
// Returns 0 first time around.
return counted;
}
}
public void test() {
CountedRandom cr = new CountedRandom(4);
for ( int i = 0; i < 50; i++ ) {
System.out.print(cr.nextInt(4)+",");
}
System.out.println();
}
Note that this will hang if you ask for too may numbers in too small a range (as I have in my test).
Prints
2,0,1,2,1,1,3,3,0,3,0,2,2,0,1,3,
and then hangs.

Related

what is the maximum possible number of monsters you can defeat?

Problem Statement:
While playing an RPG game, you were assigned to complete one of the hardest quests in this game. There are n monsters you'll need to defeat in this quest. Each monster i is described with two integer numbers - poweri and bonusi. To defeat this monster, you'll need at least poweri experience points. If you try fighting this monster without having enough experience points, you lose immediately.
You will also gain bonusi experience points if you defeat this monster. You can defeat monsters in any order. The quest turned out to be very hard - you try to defeat the monsters but keep losing repeatedly. Your friend told you that this quest is impossible to complete. Knowing that, you're interested, what is the maximum possible number of monsters you can defeat?
Input:
The first line contains an integer, n, denoting the number of monsters.
The next line contains an integer, e, denoting your initial experience.
Each line i of the n subsequent lines (where 0 ≤ i < n) contains an integer, poweri, which
represents power of the corresponding monster.
Each line i of the n subsequent lines (where 0 ≤ i < n) contains an integer, bonusi, which represents bonus for defeating the corresponding monster.
Sample cases:
Input 2 123 78 130 10 0
Output 2
Output description
Initial experience level is 123 points.
Defeat the first monster having power of 78 and bonus of 10. Experience level is now 123+10=133.
Defeat the second monster.
What I have tried:
public static int defeat(int [] monster,int bonus[],int n,int exp){
if(n==0)
return 0;
if(n==1 && monster[0]<=exp)return 1;
if(n==1 && monster[0]>exp) return 0;
if(monster[n-1]<=exp){
return defeat(monster,bonus,n-1,bonus[n-1]+exp )+ defeat(monster,bonus,n-1,exp);
}else{
return defeat(monster,bonus,n-1,exp);
}
}
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int n = s.nextInt();
int exp = s.nextInt();
int monst[] = new int[n];
int bonus[] = new int[n];
for (int i = 0; i < n; i++) {
monst[i] = s.nextInt();
}
for (int i = 0; i < n; i++) {
bonus[i] = s.nextInt();
}
System.out.println(defeat(monst,bonus,n,exp));
}
I am not getting correct answers with this solution.
I thought of this problem as 0/1 knapsack problem( correct me If I am wrong). Also can you provide me DP solution of this problem.
You can just sort the monsters from lowest to highest power required and defeat them in that order.
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int n = s.nextInt();
int exp = s.nextInt();
int monst[] = new int[n];
int bonus[] = new int[n];
for (int i = 0; i < n; i++) {
monst[i] = s.nextInt();
}
for (int i = 0; i < n; i++) {
bonus[i] = s.nextInt();
}
class Monster {
private final int power, bonus;
public Monster(int power, int bonus){
this.power = power;
this.bonus = bonus;
}
}
Monster[] monsters = new Monster[n];
for(int i = 0; i < n; i++) monsters[i] = new Monster(monst[i], bonus[i]);
Arrays.sort(monsters, Comparator.comparingInt(m -> m.power));
int count = 0;
for(Monster m: monsters){
if(exp < m.power) break;
exp += m.bonus;
++count;
}
System.out.println(count);
}
Perhaps I am too simplistic, but I would try it as below:
First create a class Monster like this:
public class Monster
{
final int m_Power;
final int m_Bonus;
public Monster( final int power, final int bonus )
{
m_Power = power;
m_Bonus = bonus;
}
public final int getPower() { return m_Power; }
public final int getBonus() { return m_Bonus; }
}
Next, initialise a list of Monsters like this:
public static void main( String... args )
{
final var scanner = new Scanner( System.in );
final var n = scanner.nextInt();
final var experience = scanner.nextInt();
final var power [] = new int [n];
for( var i = 0; i < n; ++i )
{
power [i] = scanner.nextInt();
}
List<Monster> monsters = new ArrayList<>( n );
for( var i = 0; i < n; ++i )
{
monsters.add( new Monster( power [i], scanner.nextInt();
}
monsters.sort( (m1,m2) ->
{
final var p = m1.getPower() - m2.getPower();
return p == 0 ? m2.getBonus() - m1.getBonus(() : p;
} ); //*1
System.out.println( defeat( monsters, experience ) );
}
*1 -> this implementation of the comparator works well only for power and bonus values that are small compared to MAX_INT.
The list monsters now contains the monsters sorted by their power in ascending order; monsters with the same power are ordered by their bonus values in descending order.
Now my implementation of defeat() would look like this:
public final int defeat( final List<Monster> m, final int initialExperience )
{
var experience = initialExperience;
var retValue = 0;
final Stack<Monster> monsters = new LinkedList<>( m );
while( !monsters.empty() )
{
var monster = monsters.pop();
if( experience > monster.getPower() )
{
experience += monster.getBonus();
++retValue;
}
else break;
}
return retValue;
}
n=int(input())
e=int(input())
P=[]
for i in range(n):
P.append(int(input()))
B=[]
for i in range(n):
B.append(int(input()))
c=0
f=True
while n>0 and f:
f=False
i=0
while i<n:
if e>=P[i]:
e+=B[i]
P.pop(i)
B.pop(i)
n-=1
c+=1
f=True
i-=1
i+=1
print(c)
import java.io.*;
import java.util.*;
class Player {
int exp;
public int getExp() {
return exp;
}
public void setExp(int exp) {
this.exp = exp;
}
}
class Monster {
int power;
int bonus;
public int getPower() {
return this.power;
}
public int getBonus() {
return this.bonus;
}
public void setBonus(int bonus) {
this.bonus = bonus;
}
public void setPower(int power) {
this.power = power;
}
}
class Calc {
public int calc() {
Scanner sc = new Scanner(System.in);
//number of monsters
System.out.println("enter the number of monsters");
int n = sc.nextInt();
int arr[] = new int[n];
System.out.println("enter the power of the player");
Player player = new Player();
player.setExp(sc.nextInt());
//declaration of array type object of monster
Monster monster[] = new Monster[n];
//value setting completed
for (int i = 0; i < n; i++) {
//allocation of object to the real
monster[i] = new Monster();
System.out.println("enter the power of monster");
monster[i].setPower(sc.nextInt());
System.out.println("enter the bonus that to be earned after killing the monster");
monster[i].setBonus(sc.nextInt());
}
//calculate win or loose
int count = 0;
int flag = 0;
//**
for (int i = 0; i < n; i++) {
if (player.getExp() >= monster[i].getPower()) {
player.setExp(player.getExp() + monster[i].getBonus());
count = count + 1;
// flag = flag + 1;
} else if (player.getExp() < monster[i].getPower()) {
for (int j = 0; j < n; j++)
arr[j] = i;
//count = count;
flag = flag + 1;
}
//**
for (int t = 0; t < flag; t++) {
if (player.getExp() >= monster[arr[t]].getPower()) {
count = count + 1;
}
}
}
return count;
}
}
public class Main {
public static void main(String[] args) {
// write your code here
System.out.println("welcome to the loosing game");
Calc c = new Calc();
System.out.println("no of monster killed" + c.calc());
}
}
#include<bits/stdc++.h>
using namespace std;
struct Monsters
{
int power;
int bonus;
};
class Solution
{
public:
//Function to find the maximum number of activities that can
//be performed by a single person.
static bool compare(Monsters a, Monsters b)
{
if(a.power < b.power) return 1;
else if(a.power > b.power) return 0;
else return 1;
}
int MonstersKill(vector<int> power, vector<int> bonus, int n, int exp)
{
Monsters arr[n];
for(int i = 0; i < n; i++)
{
arr[i].power = power[i];
arr[i].bonus = bonus[i];
}
sort(arr, arr+n, compare);
int count = 0;
for(int i = 0; i < n; i++)
{
if(arr[i].power <= exp)
{
count++;
exp += arr[i].bonus;
}
else
break;
}
return count;
}
};
int main()
{
int n, exp;
cin >> n >> exp;
vector<int> power(n), bonus(n);
//adding elements to arrays power and bonus
for(int i=0;i<n;i++)
cin>>power[i];
for(int i=0;i<n;i++)
cin>>bonus[i];
Solution ob;
cout << ob.MonstersKill(power, bonus, n, exp) << endl;
return 0;
}
Time Complexity : O(N * Log(N))
Auxilliary Space: O(N)

Generating 10 random numbers without duplicate with fundamental techniques

my intend is to use simplest java (array and loops) to generate random numbers without duplicate...but the output turns out to be 10 repeating numbers, and I cannot figure out why.
Here is my code:
int[] number = new int[10];
int count = 0;
int num;
while (count < number.length) {
num = r.nextInt(21);
boolean repeat = false;
do {
for (int i=0; i<number.length; i++) {
if (num == number[i]) {
repeat = true;
} else if (num != number[i] && i == count) {
number[count] = num;
count++;
repeat = true;
}
}
} while (!repeat);
}
for (int j = 0; j < number.length; j++) {
System.out.print(number[j] + " ");
}
How about you use a Set instead? If you also want to keep track of the order of insertion you can use a LinkedHashSet.
Random r = new Random();
Set<Integer> uniqueNumbers = new HashSet<>();
while (uniqueNumbers.size()<10){
uniqueNumbers.add(r.nextInt(21));
}
for (Integer i : uniqueNumbers){
System.out.print(i+" ");
}
A Set in java is like an Array or an ArrayList except it handles duplicates for you. It will only add the Integer to the set if it doesn't already exist in the set. The class Set has similar methods to the Array that you can utilize. For example Set.size() is equivalent to the Array.length and Set.add(Integer) is semi-equivalent to Array[index] = value. Sets do not keep track of insertion order so they do not have an index. It is a very powerful tool in Java once you learn about it. ;)
Hope this helps!
You need to break out of the for loop if either of the conditions are met.
int[] number = new int[10];
int count=0;
int num;
Random r = new Random();
while(count<number.length){
num = r.nextInt(21);
boolean repeat=false;
do{
for(int i=0; i<number.length; i++){
if(num==number[i]){
repeat=true;
break;
}
else if(i==count){
number[count]=num;
count++;
repeat=true;
break;
}
}
}while(!repeat);
}
for(int j=0;j<number.length;j++){
System.out.print(number[j]+" ");
}
This will make YOUR code work but #gonzo proposed a better solution.
Your code will break the while loop under the condition: num == number[i].
This means that if the pseudo-generated number is equal to that positions value (the default int in java is 0), then the code will end execution.
On the second conditional, the expression num != number[i] is always true (otherwise the code would have entered the previous if), but, on the first run, when i == count (or i=0, and count=0) the repeat=true breaks the loop, and nothing else would happen, rendering the output something such as
0 0 0 0 0 0...
Try this:
int[] number = new int[10];
java.util.Random r = new java.util.Random();
for(int i=0; i<number.length; i++){
boolean repeat=false;
do{
repeat=false;
int num = r.nextInt(21);
for(int j=0; j<number.length; j++){
if(number[j]==num){
repeat=true;
}
}
if(!repeat) number[i]=num;
}while(repeat);
}
for (int k = 0; k < number.length; k++) {
System.out.print(number[k] + " ");
}
System.out.println();
Test it here.
I believe the problem is much easier to solve. You could use a List to check if the number has been generated or not (uniqueness). Here is a working block of code.
int count=0;
int num;
Random r = new Random();
List<Integer> numbers = new ArrayList<Integer>();
while (count<10) {
num = r.nextInt(21);
if(!numbers.contains(num) ) {
numbers.add(num);
count++;
}
}
for(int j=0;j<10;j++){
System.out.print(numbers.get(j)+" ");
}
}
Let's start with the most simple approach, putting 10 random - potentially duplicated - numbers into an array:
public class NonUniqueRandoms
{
public static void main(String[] args)
{
int[] number = new int[10];
int count = 0;
while (count < number.length) {
// Use ThreadLocalRandom so this is a contained compilable unit
number[count++] = ThreadLocalRandom.current().nextInt(21);
}
for (int j = 0; j < number.length; j++) {
System.out.println(number[j]);
}
}
}
So that gets you most of the way there, the only thing you know have to do is pick a number and check your array:
public class UniqueRandoms
{
public static void main(String[] args)
{
int[] number = new int[10];
int count = 0;
while (count < number.length) {
// Use ThreadLocalRandom so this is a contained compilable unit
int candidate = ThreadLocalRandom.current().nextInt(21);
// Is candidate in our array already?
boolean exists = false;
for (int i = 0; i < count; i++) {
if (number[i] == candidate) {
exists = true;
break;
}
}
// We didn't find it, so we're good to add it to the array
if (!exists) {
number[count++] = candidate;
}
}
for (int j = 0; j < number.length; j++) {
System.out.println(number[j]);
}
}
}
The problem is with your inner 'for' loop. Once the program finds a unique integer, it adds the integer to the array and then increments the count. On the next loop iteration, the new integer will be added again because (num != number[i] && i == count), eventually filling up the array with the same integer. The for loop needs to exit after adding the unique integer the first time.
But if we look at the construction more deeply, we see that the inner for loop is entirely unnecessary.
See the code below.
import java.util.*;
public class RandomDemo {
public static void main( String args[] ){
// create random object
Random r = new Random();
int[] number = new int[10];
int count = 0;
int num;
while (count < number.length) {
num = r.nextInt(21);
boolean repeat = false;
int i=0;
do {
if (num == number[i]) {
repeat = true;
} else if (num != number[i] && i == count) {
number[count] = num;
count++;
repeat = true;
}
i++;
} while (!repeat && i < number.length);
}
for (int j = 0; j < number.length; j++) {
System.out.print(number[j] + " ");
}
}
}
This would be my approach.
import java.util.Random;
public class uniquerandom {
public static void main(String[] args) {
Random rnd = new Random();
int qask[]=new int[10];
int it,i,t=0,in,flag;
for(it=0;;it++)
{
i=rnd.nextInt(11);
flag=0;
for(in=0;in<qask.length;in++)
{
if(i==qask[in])
{
flag=1;
break;
}
}
if(flag!=1)
{
qask[t++]=i;
}
if(t==10)
break;
}
for(it=0;it<qask.length;it++)
System.out.println(qask[it]);
}}
public String pickStringElement(ArrayList list, int... howMany) {
int counter = howMany.length > 0 ? howMany[0] : 1;
String returnString = "";
ArrayList previousVal = new ArrayList()
for (int i = 1; i <= counter; i++) {
Random rand = new Random()
for(int j=1; j <=list.size(); j++){
int newRand = rand.nextInt(list.size())
if (!previousVal.contains(newRand)){
previousVal.add(newRand)
returnString = returnString + (i>1 ? ", " + list.get(newRand) :list.get(newRand))
break
}
}
}
return returnString;
}
Create simple method and call it where you require-
private List<Integer> q_list = new ArrayList<>(); //declare list integer type
private void checkList(int size)
{
position = getRandom(list.size()); //generating random value less than size
if(q_list.contains(position)) { // check if list contains position
checkList(size); /// if it contains call checkList method again
}
else
{
q_list.add(position); // else add the position in the list
playAnimation(tv_questions, 0, list.get(position).getQuestion()); // task you want to perform after getting value
}
}
for getting random value this method is being called-
public static int getRandom(int max){
return (int) (Math.random()*max);
}

Parallel sort not finding the top numbers

I'm writing a program which is supposed to find the 25 top numbers in a large array using threads. My algorithm seems to work fine, however when comparing the result to an Arrays.sort-ed version of the original array, it seems like my top 25-list misses some of the numbers. I really hate posting this much code in a question, but I'm completely stuck on this, and has been for a couple of hours now. I'd love some help figuring out what's wrong. Here are my classes:
Main.java
import java.util.Arrays;
import java.util.Random;
public class Main {
public static void main(String[] args) {
final int NUM_THRS = 4;
int[] numbers = new int[500];
Random generator = new Random(500);
for(int i = 0; i < numbers.length; i++) {
numbers[i] = Math.abs(generator.nextInt());
}
Thread[] thrs = new Thread[NUM_THRS];
NumberThread[] nthrs = new NumberThread[NUM_THRS];
long startTime = System.currentTimeMillis();
for(int i = 0; i < thrs.length; i++) {
int start = getStart(i, thrs.length, numbers.length);
int stop = getStop(i, thrs.length, numbers.length);
nthrs[i] = new NumberThread(numbers, start, stop);
thrs[i] = new Thread(nthrs[i]);
thrs[i].start();
}
for (int i = 0; i < thrs.length; i++) {
try {
thrs[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int[] top = new int[25];
int[] indices = new int[NUM_THRS];
for (int i = 0; i < indices.length; i++) {
indices[i] = 24;
}
for(int i = 0; i < top.length; i++) {
top[i] = getMax(nthrs, indices);
}
for (int i = 0; i < top.length; i++) {
System.out.println(top[i]);
}
}
public static int getMax(NumberThread[] thrs, int[] indices) {
int maxNum = 0;
int maxIdx = 0;
for(int i = 0; i < indices.length; i++) {
if(indices[i] >= 0) {
if(thrs[i].topNums[indices[i]] > maxNum) {
maxNum = thrs[i].topNums[indices[i]];
maxIdx = i;
}
}
}
System.out.println("iterate");
indices[maxIdx] = indices[maxIdx]-1;
return maxNum;
}
public static int getStart(int i, int total, int len) {
return i*len/total;
}
public static int getStop(int i, int total, int len) {
if(i != total-1) {
return (i+1)*len/total;
}
return len-1;
}
}
NumberThread.java
public class NumberThread implements Runnable {
int start, stop;
int[] numbers;
int[] topNums;
public NumberThread(int[] numbers, int start, int stop) {
this.numbers = numbers;
this.start = start;
this.stop = stop;
this.topNums = new int[25];
System.out.println(start + " " + stop);
}
#Override
public void run() {
for (int i = start; i <= stop; i++) {
inner: for (int j = topNums.length-1; j > 0; j--) {
if(numbers[i] > topNums[j]) {
topNums[j] = numbers[i];
break inner;
}
}
}
}
}
The numbers printed after main are not the same as the top numbers when I Arrays.sort the numbers-array and print the top 25. Some numbers seem to be missing.
Thanks a lot in advance.
I think that your NumberThread classes Run method isn't doing what it should do. It needs to find the 25 largest numbers in the partition you assign to it, for example if the array you are searching was already sorted then the 25 largest numbers could all be in 1 partition but what its's actually doing is overwriting the first number it finds that's smaller than the current number so you end up with less than 25 numbers and they might not be the largest.
For example consider the sequence 98 99 1 2 3... 98 would get written to topNums[19] but then overwritten with 99.
I'm also not sure about the getMax function, it seems to be trying to merge the different topNums arrays together; however the arrays aren't sorted so I don't see how it can work.

Java Simple Lottery Program

I tried to create a simple lottery program. Here is a problem: it still prints same numbers. For example I got 33 21 8 29 21 10 as output. Everytime when random number is generated, code checks if that number is already generated, then it creates a new random number but after that it doesn't check again. I couldn't find a way to do that.
public static void main(String[] args)
{
int[] lottery = new int[6];
int randomNum;
for (int i = 0; i < 6; i++)
{
randomNum = (int) (Math.random() * 50); //Random number created here.
for (int x = 0; x < i; x++)
{
if (lottery[i] == randomNum) // Here, code checks if same random number generated before.
{
randomNum = (int) (Math.random() * 50);//If random number is same, another number generated.
}
}
lottery[i] = randomNum;
}
for (int i = 0; i < lottery.length; i++)
System.out.print(lottery[i] + " ");
}
There are 2 problems with your code:
you check if lottery[i] and randomNum are the same, it should be lottery[x]
when you re-generate a random number, you don't check it against the first numbers in lottery.
Here is a corrected version:
public static void main(String[] args) {
int[] lottery = new int[6];
int randomNum;
for (int i = 0; i < 6; i++) {
randomNum = (int) (Math.random() * 50); // Random number created here.
for (int x = 0; x < i; x++) {
if (lottery[x] == randomNum) // Here, code checks if same random number generated before.
{
randomNum = (int) (Math.random() * 50);// If random number is same, another number generated.
x = -1; // restart the loop
}
}
lottery[i] = randomNum;
}
for (int i = 0; i < lottery.length; i++)
System.out.print(lottery[i] + " ");
}
You are changing the random number while you are checking it. You need to pick one random number and check whether it is present or not.
BTW A shorter approach is to use a shuffle.
// give me all the number 1 to 50
List<Integer> list = IntStream.range(1, 51).boxed().collect(Collectors.toList());
// shuffle them.
Collections.shuffle(list);
// give me the first 6
System.out.println(list.subList(0, 6));
A simple solution, between the first (who could be very abstract for a not Java programmer) and the 2nd (not assuring the unicity of the number list).
Collection<Integer> liste = new ArrayList<Integer>();
for (int i = 0; i < 6; i++)
{
Boolean ap = false;
while (!ap)
{
Integer randomNumber = (int) (Math.random() * 50);
if (! liste.contains(randomNumber)){
liste.add(randomNumber);
ap = true;
}
}
}
for (Integer liste1 : liste) {
System.out.print(liste1+" ");
}
try this one, it creates 12 x (6 out of 45)
public static void main(String[] args) {
SecureRandom random = new SecureRandom();
for (int i = 0; i < 12; i++){
Integer[] tipp = new Integer[6];
int n = 0;
do {
int r = random.nextInt(45) + 1;
if (Arrays.asList(tipp).indexOf(r)<0){
tipp[n]= r;
n++;
}
} while (n<=5);
Arrays.sort(tipp);
System.out.println(Arrays.toString(tipp));
}
}
public static void main(String[] arg) {
int[] lottery = new int[6];
int randomNum;
c1:
for (int i = 0; i < 6; i++) {
randomNum = (int) (Math.random() * 50); // Random number created here.
if(randomNum == 0) {
continue c1;
}
for (int x = 0; x < i; x++) {
if (lottery[x] == randomNum ) // Here, code checks if same random number generated before.
{
randomNum = (int) (Math.random() * 50);// If random number is same, another number generated.
x = -1; // restart the loop
}
}
lottery[i] = randomNum;
}
for (int i = 0; i < lottery.length; i++)
System.out.print(lottery[i] + " ");
}
This is the object class for making a ticket, it will create ONE ticket with ascending values at which whatever parameters you choose. This program won't run until you have a main method that you call. Make sure to import TreeSet.
import java.util.TreeSet;
public class TicketMaker{
private int numbersPerTicket;
private int lowestNumber;
private int highestNumber;
TicketMaker(){
numbersPerTicket=0;
lowestNumber=0;
highestNumber=0;
}
TicketMaker(int numbersPerTicket,int lowestNumber,int highestNumber){
if(numbersPerTicket > 0 && lowestNumber >= 0 && highestNumber >= lowestNumber){
this.numbersPerTicket=numbersPerTicket;
this.lowestNumber=lowestNumber;
this.highestNumber=highestNumber;
}
}
public boolean printTicket(int numbersPerTicket,int lowestNumber,int highestNumber){
if(numbersPerTicket > 0 && lowestNumber >= 0 && highestNumber >= lowestNumber){
if(numbersPerTicket > highestNumber){
System.out.println("Error not in-bounds");
return false;
}
int rand;
int count=0;
System.out.println("[Ticket Printed]");
TreeSet<Integer> set = new TreeSet<>();
do{
rand = (int)(Math.random()*highestNumber)+lowestNumber;
set.add(rand);
count++;
}while(set.size() != numbersPerTicket);
System.out.println(set);
return true;
}
else{
System.out.println("Error not in-bounds");
return false;
}
}
public boolean isValidTicketData(int numbers,int lowest,int highest){
if(lowest != 1){
if(highest == numbers)
return false;
}
if(numbers <= highest){
if(numbers > 0 && lowest >= 0 && highest >= lowest)
return true;
}
return false;
}
}

Weighted random numbers: boundary case

In reference to the top answer given in this post, I've noticed that it fails for a boundary case when rnd=sum_of_weight. The fix is to generate random numbers in [0,sum_of_weight), however i was wondering why the code fails for this boundary case? Is it a flaw in the algorithm?
EDIT: Also, does the weight array need to be sorted high to low? It seems so, based on the subtraction loop.
Below is the Java code that implements the pseudo-code in the above post.
int sum_of_weight = 0;
int []choice_weight = {50, 15, 15, 10, 10}; // percentages
int num_choices = choice_weight.length;
public void init() {
for (int i = 0; i < num_choices; i++) {
sum_of_weight += choice_weight[i];
}
}
int next() {
int rnd = (int)Util.between(0, sum_of_weight);// random(sum_of_weight);
rnd=sum_of_weight; // force the exception by hitting boundary case
//System.out.print("rnd=" + rnd);
for (int i = 0; i < num_choices; i++) {
if (rnd < choice_weight[i])
return i;
rnd -= choice_weight[i];
}
throw new RuntimeException("should never get here for rnd=" + rnd);
}
public static void main(String[] args) {
SimpleWeight sw = new SimpleWeight();
sw.init();
for (int i=0; i < 10;i++) {
System.out.println(sw.next());
}
}
Step 2 of the algorithm you link to states:
2) pick a random number between 0 and less than the sum weights.
To me, this reads clearly and unambiguously that the correct way is to pick a number from [0,sum_of_weight). Picking a number from a different range (e.g. any range that includes sum_of_weight) isn't a flaw in the algorithm, it's a flaw in the implementation of that algorithm.
edit No, the weights do not need to be sorted for the algorithm to work.
For those that find it useful, here is another implementation of the above. Open to feedback too if you want to make it better. I'm still a beginner.
import java.util.Random;
public class WeightedRandom {
private int choiceWeight[];
private int numChoices = 0;
private int i = 0;
private Random r = new Random();
public WeightedRandom() {
this.choiceWeight = new int[] { 60, 35, 5 };
this.numChoices = choiceWeight.length;
}
public WeightedRandom(int[] choiceWeight) {
this.choiceWeight = choiceWeight;
this.numChoices = this.choiceWeight.length;
}
public int weightedRandomGenerator() {
int sumOfWeight = 0;
for (int i = 0; i < numChoices; i++) {
sumOfWeight += choiceWeight[i];
}
int randomNumber = r.nextInt(sumOfWeight);
for (int i = 0; i < numChoices; i++) {
if (randomNumber < choiceWeight[i])
return i;
randomNumber -= choiceWeight[i];
}
throw new RuntimeException("should never get here for RandomNumber = " + randomNumber);
}
public void printWeightedAverage(int numberOfIterations) {
int numberCount[] = new int[numChoices];
for (int n = 0; n < numberOfIterations; n++) {
i = weightedRandomGenerator();
numberCount[i]++;
}
for (int n = 0; n < numChoices; n++)
System.out.println("Occurance of " + n + " = " + (((double) numberCount[n]) / numberOfIterations) * 100 + "%");
System.out.println("--------");
}
public static void main(String[] args) {
WeightedRandom wr = new WeightedRandom();
WeightedRandom wr2 = new WeightedRandom(new int[] { 49, 25, 15, 5, 3, 2, 1 });
wr.printWeightedAverage(100_000_000);
wr2.printWeightedAverage(100_000_000);
}
}

Categories

Resources