Generating Unique random numbers effectively in Java - java

I want to generate unique random numbers from range 0 to 999,999.
In order to achieve that, I tried:
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 999999; i++) {
list.add(new Integer(i)); // Add numbers from 0 - 999,999 into ArrayList
}
Collections.shuffle(list); // shuffle them
for (int i = 0; i < 10; i++) {
System.out.println(list.get(i)); // printed unique numbers
}
The problem is the larger the number I want to generate, the longer the time it takes, for the above method, it took about 700ms.
But if I use Random() to generate them without filter duplicate numbers, it only takes 2ms
for(int i = 0; i<10; i++) {
int digit = 0 + new Random().nextInt((999999 - 0) + 1);
System.out.println(digit);
}
Is there other way to generate unique random numbers in a more efficient manner?

There is no need to create a list of 1000000 numbers and shuffle them all if you only need 10. There is also no need to write new Integer(i) (you can just use i).
In Java 8 there is a very short way to do this:
int[] arr = ThreadLocalRandom.current().ints(0, 1000000).distinct().limit(10).toArray();
System.out.println(Arrays.toString(arr));
If you are using Java 7 or below, you could do this:
Random rand = new Random(); // Only do this in Java 6 or below. Now you should use ThreadLocalRandom.current().
int[] arr = new int[10];
Set<Integer> set = new HashSet<Integer>();
for (int index = 0, a; index < 10;)
if (set.add(a = rand.nextInt(1000000)))
arr[index++] = a;
System.out.println(Arrays.toString(arr));

You could create a set of random integers like this:
Set<Integer> set = new HashSet<Integer>();
Random rand = new Random();
while (set.size() < 10) {
set.add(rand.nextInt((1000000)));
}
The idea is that the set data structure will remove duplicates.

here is my code
its work perfect
private int count;
private boolean in = true;
public static final Random gen = new Random();
int[] result;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public void addUse() {
result = new int[getCount() + 10];
for (int i = 1; i < 10; i++) {
String setup = ("" + i + i + i + i + i);
result[getCount() + i] = Integer.valueOf(setup);
}
}
public boolean chechArray(int number) {
for (int i = 0; i < getCount() + 10; i++) {
if (result[i] == number) {
in = true;
break;
} else {
in = false;
}
}
return in;
}
public void printRandomNumbers() {
Random gen = new Random();
for (int i = 0; i < getCount(); i++) {
int get = gen.nextInt(100000 - 10000) + 10000;
if (chechArray(get) == false) {
result[i] = get;
} else {
i--;
}
}
}
public void viewArray() {
printRandomNumbers();
for (int i = 0; i < getCount(); i++) {
System.out.println((i + 1) + " Number is = " + result[i]);
}
}
public static void main(String[] args) {
RandomDemo3 rd2 = new RandomDemo3();
rd2.setCount(20);
rd2.addUse();
rd2.viewArray();
}

Related

Find minimum pair of numbers whose sum is 15

I am trying to find the minimum pair of numbers to achieve sum of 15. I am creating new array for them and passing that array to method which is adding element of that array and generating true or false. array size will increase if method returns false.
public class FindMinimum {
static int arr[] = { 10, 3, 2, 13 };
static int numArr[] = new int[30];
static int arrLength = 2;
static boolean status = false;
static int number;
public static void main(String args[]) {
for (int i = 0; i < arrLength; i++) {
numArr[i] = arr[i];
}
if (checkPair(numArr)) {
System.out.println("Number found");
} else {
arrLength = arrLength + 1;
System.out.println("Increasing array length by one");
}
}
public static boolean checkPair(int x[]) {
for (int i = 0; i < x.length; i++) {
number = number + x[i];
}
if (number == 15) {
status = true;
for (int i : x) {
System.out.println(i);
}
} else {
status = false;
}
return status;
}
}
Expected result is minimum pair of addition that is "13 ,2"
If I understand correctly need to find minimum pair which always add to 15. If this is correct below code should solve it.
public static void main(String args[]) {
Arrays.sort(arr);
for (int i=0,j=arr.length-1;i<arr.length && j>=0;) {
if ((arr[i]+arr[j])<15) {
/*System.out.println(arr[i]+"-"+arr[last-i]);
break;*/
i++;
} else if ((arr[i]+arr[j])>15) {
j--;
} else {
System.out.println(arr[i]+"-"+arr[j]);
break;
}
}
}
import java.util.Scanner;
public class FindMinimumPair {
static Scanner sc = new Scanner(System.in);
static int userArr[];
static int numArr[]; // New array to take number / pairs from main array to compare with else numbers
// in the main array
static int arrLength = 1; // increase the array length of numArr if pair is more than 2 numbers
static boolean status = false; // check method returns true or false
static int sum;
public static void main(String args[]) {
System.out.println("Sum of pair should be ?");
sum = sc.nextInt();
System.out.println("Enter the lenght of an array");
int userArrLength = sc.nextInt();
userArr = new int[userArrLength];
System.out.println("Enter array integers upto " + userArrLength);
for (int i = 0; i < userArrLength; i++) {
userArr[i] = sc.nextInt();
}
// Loop to read numbers from main array
for (int i = 0; i < userArr.length; i++) {
// Defines the length of new array
numArr = new int[arrLength]; // initialize the new array
// Loop to add numbers into new array
for (int j = 0; j < arrLength; j++) {
numArr[j] = userArr[j]; // add numbers into new array
}
if (check(numArr)) { // call check method and pass new array in it
for (int a : numArr) { // if returns true then print that array (contains the pair)
System.out.print(a + " ");
}
System.out.print(userArr[numArr.length]); // print the last number which is the part of numArr
System.out.println(" is equals to " + sum);
} else {
System.out.println("Numbers not found");
}
arrLength = arrLength + 1; // increase the array length if false
}
}
public static boolean check(int number[]) {
int x = 0;
// Loop to make sum of all numbers of numArr (make it single number)
for (int j = 0; j < number.length; j++) {
x = x + number[j];
}
outer: for (int i = 0; i < number.length; i++) { // loop for elements in numArr array
for (int j = 0; j < userArr.length; j++) { // loop for given array elements
if (x + userArr[j] == sum) { // check each number of given array with the sum of numArr
status = true;
break outer; // breaks outer loop and returns true
} else {
status = false;
}
}
}
return status;
}
}

randomly generate 100 unique numbers using Math.random [duplicate]

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);
}

A method or function that returns a list of pairs of numbers which would sum up to 5

I am trying to implement a function in JAVA which would give me a List of Pairs of Numbers.
This pair of numbers which would add up to 5, so ultimate goal is to print this list of pair of numbers
I have this code to determine pair but not sure how to return from method.
Please Note: I have used void as I have no clue of how to return values from method in the form {(numberA[0], numberB[0]), (numberA[1], numberB[1]), ....}?
public void setNumberList(int[] numberList) {
ArrayList<Integer> numberA = new ArrayList<Integer>();
ArrayList<Integer> numberB = new ArrayList<Integer>();
for (int i = 0; i < numberList.length; i++) {
int first = numberList[i];
for (int j = i + 1; j < numberList.length; j++) {
int second = numberList[j];
if ((first + second) == 5) {
numberA.add(first);
numberB.add(second);
}
}
}
}
You can change the return type of your method to Set<List<Integer>>. The Set will contain lists of numbers, where the numbers in each list will sum up to your target number 5. The method will look like this:
public static Set<List<Integer>> setNumberList(int[] numberList) {
ArrayList<Integer> numberA = new ArrayList<Integer>();
ArrayList<Integer> numberB = new ArrayList<Integer>();
for (int i = 0; i < numberList.length; i++) {
int first = numberList[i];
for (int j = i + 1; j < numberList.length; j++) {
int second = numberList[j];
if ((first + second) == 5) {
numberA.add(first);
numberB.add(second);
}
}
}
Set<List<Integer>> result = new HashSet<List<Integer>>();
for (int i=0; i<numberA.size(); i++) {
int n1 = numberA.get(i);
int n2 = numberB.get(i);
List<Integer> numbersToAdd = Arrays.asList(n1, n2);
result.add(numbersToAdd);
}
return result;
}

Java - (Print distinct numbers)

I'm trying to solve this problem:
"Write a program that reads in ten numbers and displays the number of distinct numbers and the distinct numbers separated by exactly one space."
My code at the moment does not save all distinct numbers and at time repeatedly display 0. If anyone can see where my logic has gone wrong, any tip will be helpful. Thank you!
public class PracticeProject
{
public static void main(String args[])
{
int[] number = new int[10];
int[] counter = new int[10];
int numcounter = 0;
numGen(number);
numcounter = distNum(number, counter, numcounter);
dispDist(counter, numcounter);
}
public static void numGen(int[] number)
{
Random rand = new Random();
for (int i = 0; i < number.length; i++)
{
number[i] = rand.nextInt(10);
System.out.print(number[i] + " ");
}
System.out.println();
}
public static int distNum(int[] number, int[] counter, int numcounter)
{
for (int i = 0; i < number.length; i++)
{
for (int j = 0; j <= i; j++)
{
if (counter[j] == number[i])
{
break;
}
if (j == i)
{
counter[j] = number[i];
numcounter++;
}
}
}
return numcounter;
}
public static void dispDist(int[] counter, int numcounter)
{
for (int i = 0; i < numcounter; i++)
{
System.out.print(counter[i] + " ");
}
}
}
The problem is with the logic in your distNum() method, which was not correctly removing all duplicates from the output array. Try using this version instead:
public static int distNum(int[] number, int[] counter, int numcounter) {
for (int i = 0; i < number.length; i++) {
boolean isUnique = true;
for (int j = 0; j < numcounter; j++) {
if (counter[j] == number[i]) {
isUnique = false;
break;
}
}
if (isUnique) {
counter[numcounter] = number[i];
numcounter++;
}
}
return numcounter;
}
I walk through the array of random numbers, and for each one I scan counter to see if the value has already been encountered. If it be a duplicate, then it does not get added to the unique list.
This method was tested along with the rest of your original code using IntelliJ, and it appears to be working correctly.
If you use array to store your counters, you need to set default value, otherwise if your array have multiple 0, it distinguish by equaling. because the int array default values is 0.
and you can use list or vector to store your counters.
public static void main(String args[]) {
int[] number = new int[10];
int[] counter = new int[10];
List<Integer> counters = new ArrayList<Integer>();
int numcounter = 0;
numGen(number);
numcounter = distNum(number, counters, numcounter);
dispDist(counters, numcounter);
}
public static void numGen(int[] number) {
Random rand = new Random();
for (int i = 0; i < number.length; i++) {
number[i] = rand.nextInt(10);
System.out.print(number[i] + " ");
}
System.out.println();
}
public static int distNum(int[] number, List<Integer> counters, int numcounter) {
for (int i : number) {
if (!counters.contains(i)){
counters.add(i);
}
}
return numcounter;
}
public static void dispDist(List<Integer> counter, int numcounter) {
for (Integer i : counter) {
System.out.print(i + " ");
}
}
Try put below function .... using Hashmap... Key will be no. and value will be the disctinct time it occured.
public void duplicate(int[] a) {
HashMap<Integer, Integer> h = new HashMap<Integer, Integer>();
for (int i = 0; i < a.length; i++) {
Integer j = (int) h.put(a[i], 1);
if (j != null) { // checking if already in hashmap
h.put(a[i], j + 1); // if there then incrementing value
}
}
Iterator it = h.entrySet().iterator(); // displaying value you can have you logic here
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
System.out.println(pair.getKey() + " = " + pair.getValue());
it.remove(); // avoids a ConcurrentModificationException
}
}

Suggest some more optimised solution for this rand generator

I have a function 'generateRan' that generates random numbers. This function can not be changed.
int generateRan() {
Random num = new Random();
return (1 + num.nextInt(100));
}
I have to write code that will:
Print numbers 1-20 randomly.
Print numbers 1-200 randomly.
Each number should be printed only once.
The function can be used any number of times. But it is a bit heavy so I want to make the code more optimized.
Here is what I've coded:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Test {
public static void main(String[] args) {
List<String> list = new ArrayList();
Test t = new Test();
iniList(list, 20);
for (Integer i = ((t.generateRan()) % 20); list.size() > 0; i = 1+((t
.generateRan()) % 20)) {
if (list.contains(i.toString())) {
list.remove(i.toString());
System.out.println(i);
}
}
System.out.println("********");
iniList(list, 200);
for (Integer i = ((t.generateRan()%2)*100 + t.generateRan()) ; list.size() > 0; i = ((t.generateRan()%2)*100 + t.generateRan())) {
if (list.contains(i.toString())) {
list.remove(i.toString());
System.out.println(i);
}
}
}
private static void iniList(List list, int i) {
for (Integer k = 1; k <= i; k++) {
list.add(k.toString());
}
}
int generateRan() {
Random num = new Random();
return (1 + num.nextInt(100));
}
}
Currently the code for 1-200 is incorrect.
Each numbers should print only once
Then all you need to to is create a List<Integer> of the entire range, then call Collections.shuffle.
private static void displayNumbers(int minInclusive, int maxInclusive) {
List<Integer> list = new ArrayList<Integer>();
for (int i = minInclusive; i <= maxInclusive; i++) {
list.add(i);
}
Collections.shuffle(list);
for (int value : list) {
System.out.println(value);
}
}
Personally I'd normally use parameters of minInclusive, maxExclusive or minInclusive, count, but it looks like it may be more readable this way for your situation.
Assuming you have to use your generateRan() function, otherwise use Collections.shuffle as indicated.
public static void main(String[] args) {
List<Integer> list = new ArrayList();
initList(list, 200);
while (list.size() > 0) {
int index = generateRan() % list.size();
System.out.println(list.remove(index));
}
}
public static void initList(List<Integer> s, int size) {
for (int i = 1; i <= size; i ++)
s.add(i);
}
public static int generateRan() {
Random num = new Random();
return (1 + num.nextInt(100));
}
You add all the ints you want to print to your list, then only use random to choose which one of these to print. Your function is called n times.
I would recomment using a Set rather than a List, for it's faster in searching for duplicates
Set<Integer> set = new HashSet<Integer>();
for(int i = 0; i < 20;) {
Integer r = generateRan();
if(set.add(r)) {
System.out.println(r);
++i;
}
}

Categories