Generate a random two-dimensional array of non-repeating numbers, Java - java

The user will type in the number for i (variant), then the number for j (elements for every variant), and finally the maximum value possible (maxElem).
Using the inputed values, the task is to generate nonrepeating random numbers (nonrepeating in a variant, meaning for i, but the numbers may repeat during the entire array).
For example, a successful output giving the input 3 (i), 5 (j), 9 (maxElem), would be:
4|8|1|7|9
3|8|2|4|5
2|6|4|8|5
As you may notice, the number 4 repeats itself during the entire array for 3 times (allowable). But, for i=0, number 4 is unique.
Please, guide me what would be the changes to this code:
static Scanner sc = new Scanner(System.in);
static int maxElem;
public static void main(String[] args) {
int[][] greatLoto;
System.out.println("Of how many variants will the ticket consist? ");
int variants = sc.nextInt();
System.out.println("Of how many elements will the variants consist? ");
int elements = sc.nextInt();
System.out.println("Which value should be considered the maximum value? ");
maxElem = sc.nextInt() + 1;
greatLoto = new int[variants][elements];
System.out.println("Initial values: ");
show(greatLoto);
System.out.println("Modifying values...");
modified(greatLoto);
System.out.println("Newest values: ");
show(greatLoto);
}
private static void show(int[][] greatLoto) {
for (int i = 0; i < greatLoto.length; i++) {
for (int j = 0; j < greatLoto[i].length; j++) {
System.out.print("|" + greatLoto[i][j] + "|");
}
System.out.println("");
}
System.out.println("");
}
private static void modified(int[][] greatLoto) {
Random r = new Random(System.currentTimeMillis());
for (int i = 0; i < greatLoto.length; i++) {
for (int j = 0; j < greatLoto[i].length; j++) {
while (Arrays.asList(greatLoto[i]).contains(r)) {
r = new Random(System.currentTimeMillis());
}
greatLoto[i][j] = r.nextInt(maxElem);;
}
System.out.println("");
}
}

This is more of a comment but too long: don't use random.next() because it forces you to check for uniqueness. Instead fill a list with the valid values and shuffle it:
List<Integer> values = new ArrayList<> ();
for (int i = 1; i <= max; i++) values.add(i);
Collections.shuffle(values);
Then you can simply iterate over the values and take the j first numbers.
Note that if j is significantly greater than i using the random approach would probably be more efficient.

The most minimal change would be:
private static void modified(int[][] greatLoto) {
Random r = new Random(System.currentTimeMillis());
for (int i = 0; i < greatLoto.length; i++) {
for (int j = 0; j < greatLoto[i].length; j++) {
do {
greatLoto[i][j] = r.nextInt(maxElem);
} while (Arrays.asList(greatLoto[i]).contains(greatLoto[i][j]));
}
System.out.println("");
}
}
But there are more elegant (but difficult to code) ways to generate unique random numbers without discarding duplicates.

You need three loops:
Loop_1: Builds an array of size j and uses Loop_1B for every field of this array.
Loop_1B: Generate an int with r.nextInt(maxElem)+1; (it has to be +1 because nextInt() is covering the 0 inclusively and the specified value exclusively). Afterwards check if the number is already used in the array, if yes, run this loop again.
Loop_2: Repeats Loop_1 i times.

Related

I don't know how assign new value to the empty array

I am a beginner in coding. I have to write a code that will divide array with random numbers into two different arrays. One array will contain odd numbers, the other one even numbers. But something is wrong, and i don't really know what to do.
According to the console the problem is in the place where there is a lot of exclamation marks. when i change those lines to System.out.println("x") it works perfectly fine.
public void P_N () {
int I_E = 0; // amount of even numbers
int I_O = 0; // amount of odd numbers
for (int i = 0; i < tab2.length; i++) { // tab2 is a array with random numbers
if (tab2[i] % 2 == 0)
I_E = I_E + 1;
else
I_O = I_O+1;
}
int [] tab_E = new int[I_E]; // array with even numbers
int [] tab_O = new int [I_O]; // array with odd numbers
for (int i = 0; i < tab2.length; i++){
if (tab2[i] % 2 == 0){
tab_E[i] = tab2[i]; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
for (int i = 0; i < tab2.length; i++){
if (tab2[i] % 2 != 0){
tab_O[i] = tab2[i]; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
for (int i = 0; i< tab_E.length; i++) {
System.out.println("Even array: " + tab_E[i]);
System.out.println("------------------------------------------------");
}
for (int i = 0; i< tab_O.length; i++) {
System.out.println("Odd array: " + tab_O[i]);
}
}
Problem is in going out of bounds for arrays tab_E and tab_O, when variable i is more tab_E.length. Just create another variable, for example "j". And iterate throug your array using it. Like I'v written below
int j = 0;
for (int i = 0; i < tab2.length; i++) {
if (tab2[i] % 2 == 0) {
tab_E[j++] = tab2[i];
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
j = 0;
for (int i = 0; i < tab2.length; i++) {
if (tab2[i] % 2 != 0) {
tab_O[j++] = tab2[i];
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
I would rather use 2 ArrayLists one for even numbers and another one is for odd numbers and later convert it into array using toArray() method.
public void P_N(){
ArrayList<Integer> evenNumberList = new ArrayList<Integer>();
ArrayList<Integer> oddNumberList = new ArrayList<Integer>();
for (int i = 0; i < tab2.length; i++) { // tab2 is a array with random numbers
if (tab2[i] % 2 == 0) {
evenNumberList.add(tab2[i]);
} else {
oddNumberList.add(tab2[i]);
}
}
int[] evenNumberArray = evenNumberList.toArray();
int[] oddNumberArray = oddNumberList.toArray();
}
This will take some extra space but makes your application more efficient, I hope this helps.
You have initialized the even/odd number arrays with a quantity of the even/odd numbers accordingly:
int [] tab_E = new int[I_E]; // array with even numbers
int [] tab_O = new int [I_O]; // array with odd numbers
Ii is reasonable to assume that the sizes of even or odd number arrays are might be much smaller than the size of the original source array.
But in this even number filtering loop (as well as in the odd filtering loop) you use source array index values to address target array positions, end eventually face the ArrayIndexOutOfBoundsException.
for (int i = 0; i < tab2.length; i++)
{
if (tab2[i] % 2 == 0)
{
tab_E[i] = tab2[i]; //here the same i value is used to address non existing index in tab_E array
}
}
A quick fix might be the following:
int tab_E_index = 0;
for (int i = 0; i < tab2.length; i++){
if (tab2[i] % 2 == 0){
tab_E[tab_E_index] = tab2[i]; //i value gets incremented every loop iteration
tab_E_index++; //tab_E_index value get incremented only when even number is added to the tab_E array
}
}
Please don't just copy/paste it, but try to understand what caused the issue on the first place. Good luck and happy coding.

How to remove duplicates from array using for loop

In this code I have found duplicates from an array and I want to remove them. The output then will be unique generated numbers. I am required to use math.random and modulo. Anyone have any clues? I tried to store them in an array but then the original array has 0's and 0 is part of my domain for the random number generation (from 0 to 52).
public class Decks {
public static void main(String[] args) {
generate();
}
public static void generate() {
int deckOfCard[] = new int[52];
for (int counts = 0; counts < 52; counts++) {
deckOfCard[counts] = (int) (Math.random() * 51);
}
for (int i = 0; i < deckOfCard.length - 1; i++) {
for (int j = i + 1; j < deckOfCard.length; j++) {
if ((deckOfCard[i] == (deckOfCard[j])) && (i != j)) {
System.out.println("DUPLICATE " + deckOfCard[i]);
}
}
}
for (int count = 0; count < deckOfCard.length; count++) {
System.out.print("\t" + deckOfCard[count]);
}
}
Why dont you try using HashSet instead of arrays ? As you know sets only store unique values so you wont have any duplicates.
You must validate the numbers generated during the random number generation like this:
import java.util.Random;
public class Decks {
public static void main(String[] args) {
Random myRandom = new Random();
int[] num = new int[53];
boolean[] check = new boolean[53];
int all = 0;
int ranNum;
while (all < 53) {
ranNum = myRandom.nextInt(53);
if (!check[ranNum]) {
check[ranNum] = true;
num[all] = ranNum;
all++;
}
}
for (int i = 0; i < 53; i++) {
System.out.println(num[i]);
}
}
}
I suggest not including number 0 because it does not exist in a real deck of cards (ACE being the lowest having the number value of 1). I just included it right here because in my understanding, 0 is included in your desired output.
Considering time complexity, you can sort them first, which at best case takes nlogn time, and then use O(1) to find duplicated elements out.

Is there something wrong with my nested for-loop? counting and incrementing values of arrays

So, I generate a 100 numbers between the range of 0 and 9. I store these 100 numbers in an array called 'array'. Then I have the array called 'count'. It has 10 elements, and I wanted to check the following: for each element in 'array' if it equals to 0-9 then count[0-9] increments by 1, count[0] = how many times number 0 appears and so on count[1] = 1, count[2] = 2... . I just keep getting the output of around 20k numbers and i suppose? the sum of each element?, no idea why. I was wondering if there is something major wrong with my for loop?
import java.util.*;
class RandomInt {
public static void main(String[] args) {
int size = 100;
int max = 10;
int[] array = new int[size];
int[] count = new int[max]; //count[0,0,0,0,0,0,0,0,0,0]
int loop = 0;
Random generator = new Random();
for (int i = 0; i < size; i++) {
array[i] = generator.nextInt(max); // Generates 100 random numbers between 0 and 9 and stores them in array[]
System.out.print(array[i]);
for (int x = 0; x < size; x++) {// loop through 10 elements in count
for(int j = 0; j < 10; j++){ //loop through 100 elements in array
if (array[x] == j) {// loop through each 100 elements of array[x] and if element array[x] = value
count[j] += 1; // then count[x] = x + 1
System.out.print(count[j]);
}
}
}
}
System.out.println("0 appears " + count[0] + " times.");
}
}
Your Login is Perfect only mistake which i found u made is with the brackets........!
Generate the numbers using first loop and then count the number of occurrence using different for loop.
Here is your code's modified version which generates 10 numbers and counts the individual number occurrence count.....
public class RandomInt {
public static void main(String[] args) {
int size = 10;
int max = 10;
int[] array = new int[size];
int[] count = new int[max]; //count[0,0,0,0,0,0,0,0,0,0]
int loop = 0;
Random generator = new Random();
for (int i = 0; i < size; i++)
{
array[i] = generator.nextInt(max); // Generates 100 random numbers between 0 and 9 and stores them in array[]
System.out.print(array[i]+" ");
}
for (int x = 0; x < size; x++)
{// loop through 10 elements in count
for(int j = 0; j < 10; j++)
{ //loop through 100 elements in array
if (array[x] == j)
{// loop through each 100 elements of array[x] and if element array[x] = value
count[j] += 1; // then count[x] = x + 1
//System.out.print(count[j]);
}
}
}
System.out.println("3 appears " + count[3] + " times.");
}
}
There's a simpler way to do this without nested loops, so forgive me for suggesting this as a fix rather than finding the issue in the loop.
for(int i=0; i<size; i++){
int num = generator.nextInt(max);
array[i] = num;
count[num]++;
}
One loop, incrementing the count for each number as it appears. You may need to ensure all the entries in count start at 0, but even then an additional loop through 10 entries is MUCH faster.
To increment your counter, you don't need to have two nested for loops. Instead, you can use the value of array[x] as your counter.
for (int i = 0; i < size; i++) {
count[array[i]]++
}
You've nested your counting loop inside of your random number generating loop. Move the counting part outside.
Edit: The reason you're getting like 20k or whatever instances of zero is because when you set array[0] with a random value, you also check how many instances of 0 are in array[1] to array[99].
You probably shouldn't do your count until you have finished assigning your numbers, but here is how you could. Note that you want the value at array[i] to be your index to count.
for (int i = 0; i < size; i++) {
array[i] = generator.nextInt(max); // Generates random numbers
count[array[i]]++;
}
System.out.println(Arrays.toString(array));
System.out.println(Arrays.toString(count));

2D Array in Java with number manipulation

My goal is to
Create a 5x5 array and fill it with random integers in the range of 1 to 25.
Print this original array
Process the array, counting the number of odds, evens, and summing all of the elements in the array.
Print the total odds, evens, and the sum.
Im not sure how to do it and my teacher is very confused and cannot help me. I was wondering if i could get some guidance.
Here is my code:
public class Processing {
public static void main(String[] args) {
Random Random = new Random();
int[][] Processing = new int[5][5];
for (int x = 0; x < 5; x++) {
int number = Random.nextInt(25);
Processing[x] = number;
}
for (int i = 0; i < 5; i++) {
Processing[i] = new int[10];
}
}
}
Please follow naming conventions for your variables. See here: http://en.wikipedia.org/wiki/Naming_convention_(programming)#Java
Anyways, you have to nest your loops as follows:
for(int i = 0; i < 5; i ++) {
for(int j = 0; j < 5; j++) {
yourArray[i][j] = random.nextInt(25);
}
}
i is the row number and j is the column number, so this would assign values to each element in a row, then move on to the next row.
I'm guessing this is homework so I won't just give away the answer to your other questions, but to set you on the right track, here's how you would print the elements. Again, use two nested loops:
for(int i = 0; i < 5; i ++) {
for(int j = 0; j < 5; j++) {
// print elements in one row in a single line
System.out.print(yourArray[i][j] + " ");
}
System.out.println(); //return to the next line to print next row.
}

Non-repeating random numbers inside array JAVA

I would like to generate 6 numbers inside an array and at the same time, having it compared so it will not be the same or no repeating numbers. For example, I want to generate 1-2-3-4-5-6 in any order, and most importantly without repeating. So what I thought is to compare current array in generated array one by one and if the number repeats, it will re-run the method and randomize a number again so it will avoid repeating of numbers.
Here is my code:
import javax.swing.*;
public class NonRepeat
{
public static void main(String args[])
{
int Array[] = new int [6];
int login = Integer.parseInt(JOptionPane.showInputDialog("ASD"));
while(login != 0)
{
String output="";
for(int index = 0; index<6; index++)
{
Array[index] = numGen();
for(int loop = 0; loop <6 ; loop++)
{
if(Array[index] == Array[loop])
{
Array[index] = numGen();
}
}
}
for(int index = 0; index<6; index++)
{
output += Array[index] + " ";
}
JOptionPane.showMessageDialog(null, output);
}
}
public static int numGen()
{
int random = (int)(1+Math.random()*6);
return random;
}
}
I've been thinking it for 2 hours and still cant generate 6 numbers without repeating.
Hope my question will be answered.
Btw, Im new in codes so please I just want to compare it using for loop or while loop and if else.
You can generate numbers from, say, 1 to 6 (see below for another solution) then do a Collections.shuffle to shuffle your numbers.
final List<Integer> l = new ArrayList<Integer>();
for (int j = 1; j < 7; j++ ) {
l.add( j );
}
Collections.shuffle( l );
By doing this you'll end up with a randomized list of numbers from 1 to 6 without having twice the same number.
If we decompose the solution, first you have this, which really just create a list of six numbers:
final List<Integer> l = new ArrayList<Integer>();
for (int j = 1; j < 7; j++ ) {
l.add( j );
}
So at this point you have the list 1-2-3-4-5-6 you mentioned in your question. You're guaranteed that these numbers are non-repeating.
Then you simply shuffle / randomize that list by swapping each element at least once with another element. This is what the Collections.shuffle method does.
The solutions that you suggested isn't going to be very efficient: depending on how big your list of numbers is and on your range, you may have a very high probability of having duplicate numbers. In that case constantly re-trying to generate a new list will be slow. Moreover any other solution suggesting to check if the list already contains a number to prevent duplicate or to use a set is going to be slow if you have a long list of consecutive number (say a list of 100 000 numbers from 1 to 100 000): you'd constantly be trying to randomly generate numbers which haven't been generated yet and you'd have more and more collisions as your list of numbers grows.
If you do not want to use Collections.shuffle (for example for learning purpose), you may still want to use the same idea: first create your list of numbers by making sure there aren't any duplicates and then do a for loop which randomly swap two elements of your list. You may want to look at the source code of the Collections.shuffle method which does shuffle in a correct manner.
EDIT It's not very clear what the properties of your "random numbers" have to be. If you don't want them incremental from 1 to 6, you could do something like this:
final Random r = new Random();
final List<Integer> l = new ArrayList<Integer>();
for (int j = 0; j < 6; j++ ) {
final int prev = j == 0 ? 0 : l.get(l.size() - 1);
l.add( prev + 1 + r.nextInt(42) );
}
Collections.shuffle( l );
Note that by changing r.nextInt(42) to r.nextInt(1) you'll effectively get non-repeating numbers from 1 to 6.
You have to check if the number already exist, you could easily do that by putting your numbers in a List, so you have access to the method contains. If you insist on using an array then you could make a loop which checks if the number is already in the array.
Using ArrayList:
ArrayList numbers = new ArrayList();
while(numbers.size() < 6) {
int random = numGen(); //this is your method to return a random int
if(!numbers.contains(random))
numbers.add(random);
}
Using array:
int[] numbers = new int[6];
for (int i = 0; i < numbers.length; i++) {
int random = 0;
/*
* This line executes an empty while until numGen returns a number
* that is not in the array numbers yet, and assigns it to random
*/
while (contains(numbers, random = numGen()))
;
numbers[i] = random;
}
And add this method somewhere as its used in the snippet above
private static boolean contains(int[] numbers, int num) {
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] == num) {
return true;
}
}
return false;
}
Here is the solution according to your code -
You just need to change the numGen method -
public static int numGen(int Array[])
{
int random = (int)(1+Math.random()*6);
for(int loop = 0; loop <Array.length ; loop++)
{
if(Array[loop] == random)
{
return numGen(Array);
}
}
return random;
}
Complete code is -
import javax.swing.*;
public class NonRepeat
{
public static void main(String args[])
{
int login = Integer.parseInt(JOptionPane.showInputDialog("ASD"));
while(login != 0)
{
int Array[] = new int [6];
String output="";
for(int index = 0; index<6; index++)
{
Array[index] = numGen(Array);
}
for(int index = 0; index<6; index++)
{
output += Array[index] + " ";
}
JOptionPane.showMessageDialog(null, output);
}
}
public static int numGen(int Array[])
{
int random = (int)(1+Math.random()*6);
for(int loop = 0; loop <Array.length ; loop++)
{
if(Array[loop] == random)
{
return numGen(Array);
}
}
return random;
}
}
Use List instead of array and List#contains to check if number is repeated.
you can use a boolean in a while loop to identify duplicates and regenerate
int[] array = new int[10]; // array of length 10
Random rand = new Random();
for (int i = 0 ; i < array.length ; i ++ ) {
array[i] = rand.nextInt(20)+1; // random 1-20
boolean found = true;
while (found) {
found = false;
// if we do not find true throughout the loop it will break (no duplicates)
int check = array[i]; // check for duplicate
for (int j = 0 ; j < i ; j ++) {
if ( array[j] == check ) {
found = true; // found duplicate
}
}
if (found) {
array[i] = rand.nextInt(20)+1 ; // replace
}
}
}
System.out.println(Arrays.toString(array));
You may use java.util.Random. And please specify if you want any random number or just the number 1,2,3,4,5,6. If you wish random numbers then , this is a basic code:
import java.util.*;
public class randomnumber
{
public static void main(String[] args)
{
Random abc = new Random();
int[] a = new int[6];
int limit = 100,c=0;
int chk = 0;
boolean y = true;
for(;c < 6;)
{
int x = abc.nextInt(limit+1);
for(int i = 0;i<a.length;i++)
{
if(x==a[i])
{
y=false;
break;
}
}
if(y)
{
if(c!=0)if(x == (a[c-1]+1))continue;
a[c]=x;
c++;
}
}
for (Integer number : a)
{
System.out.println(number);
}
}
}
if you don't understand the last for loop , please tell , i will update it.
Use List and .contains(Object obj) method.
So you can verify if list has the random number add before.
update - based on time you can lost stuck in random loop.
List<Integer> list = new ArrayList<Integer>();
int x = 1;
while(x < 7){
list.add(x);
x++;
}
Collections.shuffle(list);
for (Integer number : list) {
System.out.println(number);
}
http://docs.oracle.com/javase/7/docs/api/java/util/List.html#contains(java.lang.Object)

Categories