Let's say I want to generate 20 random numbers on a 8 by 6 grid.(8 columns, 6 rows) . Based on the answer from here:Creating random numbers with no duplicates, I wrote my code like this:
Random randomNumGenerator = new Random();
Set<Integer[][]> generated = new LinkedHashSet<Integer[][]>();
while (generated.size() < 20) {
int randomRows = randomNumGenerator.nextInt(6);
int randomColumns = randomNumGenerator.nextInt(8);
generated.add(new Integer[][]{{randomRows,randomColumns}});
}
In reality what happens is the Set see Integer[][]{{5,5}}; and Integer[][]{{5,5}};as NOT duplicate.Why? Even tho my purpose is to get 20 non-duplicate pair of numbers, this does not work. How do I fix this?
The Set checks for duplicates using the equals method (and also the hashCode method) of its inner type, but the Integer[][]'s equals method compares the memory addresses and not the contents.
Why do you use a Set of Integer[][] if you just want to store pairs?
Unfortunately, in Java there is no Pair class, but if you do not want to create your own, you can use the Map.Entry for that.
Random randomNumGenerator = new Random();
Set<Map.Entry<Integer, Integer>> generated = new LinkedHashSet<>();
while (generated.size() < 20) {
int randomRows = randomNumGenerator.nextInt(6);
int randomColumns = randomNumGenerator.nextInt(8);
generated.add(new AbstractMap.SimpleEntry<>(randomRows,randomColumns));
}
System.out.println(generated);
Array equals is == in Java, so an array is only equal to itself. Normaly you use Arrays.equals(array1, array2) to compare them by content, but in this case, arrays are simply the wrong choice. You can either create a bean, as rafalopez79 suggested of use an array of Collections (List in your case), as a List will compare the content on equals, see the documentation. Choice is pretty much yours, a bean would probably be a bit cleaner.
How about this code. I ran it through the debugger, it works nicely and yes, the contains() method checks the value of the Integer, not the reference. You can change the range of the random number as needed, I used 5 to facilitate testing. Yes I know it's not very robust, as written this will be an endless loop (because of the limited range of 5) but it's a simple example to make the point.
UPDATE: Actually this has a bug in that it won't check for uniqueness across all the rows, but that's easily fixed as well. I just re-read the original question and looking at the original code I'm not sure I know what you want exactly. If you just want a grid with 48 unique Intergers arranged 8 by 6 this will do it, but there are several ways to do this.
final int rows = 6;
final int cols = 8;
Random randomGenerator = new Random();
ArrayList[] grid = new ArrayList[rows];
for(int i=0; i<rows; i++)
{
grid[i] = new ArrayList<Integer>();
for(int j=0; j<cols; j++)
{
for(;;)
{
Integer newInt = new Integer(randomGenerator.nextInt(5));
if(!grid[i].contains(newInt))
{
grid[i].add(newInt);
break;
}
}
}
}
Related
This is a chunk of code in Java, I'm trying to output random numbers from the tasks array, and to make sure none of the outputs are repeated, I put them through some other loops (say you have the sixth, randomly-chosen task "task[5]"; it goes through the for loop that will check it against every "tCheck" element, and while task[5] equals one of the tCheck elements, it will keep trying to find another option before going back to the start of the checking forloop... The tCheck[i] elements are changed at the end of each overall loop of output to the new random number settled on for the task element).
THE PROBLEM is that, despite supposedly checking each new random task against all tCheck elements, sometimes (not always) there are repeated tasks output (meaning, instead of putting out say 2,3,6,1,8,7,5,4, it will output something like 2,3,2,1,8,7,5,4, where "2" is repeated... NOT always in the same place, meaning it can sometimes end up like this, too, where "4" is repeated: 3,1,4,5,4,6,7,8)
int num = console.nextInt();
String[] tasks = {"1","2","3","4","5","6","7","8"};
String[] tCheck = {"","","","","","","",""};
for(int i = 0; i<= (num-1); i++){
int tNum = rand.nextInt(8);
for(int j = 0; j <=7; j++){
if(tasks[tNum].equals(tCheck[j])){
while(tasks[tNum].equals(tCheck[j])){
tNum = rand.nextInt(8);
}
j = 0;
}
}
tCheck[i] = tasks[tNum];
System.out.println(tasks[tNum]+" & "+tCheck[i]);
}
None of the other chunks of code affect this part (other than setting up Random int's, Scanners, so on; those are all done correctly). I just want it to print out each number randomly and only once. to never have any repeats. How do I make it do that?
Thanks in advance.
Firstly, don't use arrays. Use collections - they are way more programmer friendly.
Secondly, use the JDK's API to implement this idea:
randomise the order of your elements
then iterate over them linearly
In code:
List<String> tasks = Arrays.asList("1","2","3","4","5","6","7","8");
Collections.shuffle(tasks);
tasks.forEach(System.out::println);
Job done.
you can check if a certain value is inside your array with this approach.
for(int i = 0; i<= (num-1); i++){
int tNum = rand.nextInt(8);
boolean exist = Arrays.asList(tasks).contains(tNum);
while(!exist){
//your code
int tNum = rand.nextInt(8);
exist = Arrays.asList(tasks).contains(tNum);
}
}
if you are using an arraylist then you can check it with contains method since you are using an array we have to get the list from the array using asList() and then use the contains method. with the help of the while loop it will keep generating random numbers untill it generates a non duplicate value.
I used to created something similar using an ArrayList
public class Main {
public static void main(String[] args) {
String[] array = { "a", "b", "c", "d", "e" };
List<String> l = new ArrayList<String>(Arrays.asList(array));
Random r = new Random();
while(!l.isEmpty()){
String s = l.remove(r.nextInt(l.size()));
System.out.println(s);
}
}
}
I remove a random position in the list until it's empty. I don't use any check of content. I believe that is kind of effective (Even if I create a list)
I am trying to generate n random numbers between 0-31 in my Android code.
Below is the code that I am using:
int max_range = 31;
SecureRandom secureRandom = new SecureRandom();
int[] digestCodeIndicesArr = new int[indices_length];
int i = 0, random_temp = 0;
while (i != indices_length-1) {
random_temp = secureRandom.nextInt(max_range);
if (!Arrays.asList(digestCodeIndicesArr).contains(random_temp)) {
digestCodeIndicesArr[i] = random_temp;
i++;
}
}
indices_length is the number of random numbers that I need. It's generally 6,7 or 9. But when I print the generated array, I generally end up seeing duplicates. Can someone point out the mistake I am making. I have added the below line of code to filter out random duplicates:
if (!Arrays.asList(digestCodeIndicesArr).contains(random_temp))
Thanks in advance!
Arrays.asList(digestCodeIndicesArr) does not produce a List<Integer> with size() == digestCodeIndicesArr.length.
It produces a List<int[]> with size() == 1, where first (and only) element is the array.
As such, it will never contain random_temp, so ! contains() is always true.
It is bad for performance to constantly create a list and perform a sequential search to check for duplicates. Use a Set instead, that you maintain in parallel with the array, or use a LinkedHashSet first, then convert to array.
Anyway, this explains why your code wasn't working. The duplicate link that Tunaki had provided and the duplicate link I provided in comment, explains how to actually do what you were trying to do.
You need to change:
int[] digestCodeIndicesArr = new int[indices_length];
to:
Integer[] digestCodeIndicesArr = new Integer[indices_length];
because Arrays.asList(digestCodeIndicesArr) is List<int[]>, and not what you thought probably (List<int> or List<Integer> I guess).
I'm currently working on a homework assignment for a beginner-level class and I need help building a program that tests if a sodoku solution presented as an int[][] is valid. I do this by creating helper methods that check both rows, columns and grids.
To check the column I call a method called getColumn that returns a column[]. When I test it out it works fine. I then pass it out on a method called uniqueEntries that makes sure that there are no duplicates.
Problem is, when I call my getColumn method, it returns an array consisting of only one number (for example 11111111, 22222222, 33333333). I have no idea why it does that. Here is my code:
int[][] sodokuColumns = new int[length][length];
for(int k = 0 ; k < sodokuPuzzle.length ; k++) {
sodokuColumns[k] = getColumn(sodokuPuzzle, k);
}
for (int l = 0; l < sodokuPuzzle.length; l++) {
if(uniqueEntries(sodokuColumns[l]) == false) {
columnStatus = false;
}
}
my helper is as follows
public static int[] getColumn(int[][] intArray, int index) {
int[] column = new int[intArray.length];
for(int i = 0 ; i < intArray.length ; i++) {
column[i] = intArray[i][index];
}
return column;
}
Thanks !
You said:
when I call my getColumn method, it returns an array consisting of only one number (for example 11111111, 22222222, 33333333).
I don't see any issue with your getColumn method other than the fact it's not even needed because getColumn(sodokuPuzzle, k) is the same as sodokuPuzzle[k]. If you're going to conceptualize your 2D array in such a way that your first index is the column then for your purpose of checking uniqueness you only need to write a method to get rows.
The issue you're having would seem to be with another part of your code that you did not share. I suspect there's a bug in the logic that accepts user input and that it's populating the puzzle incorrectly.
Lastly a tip for checking uniqueness (if you're allowed to use it) would be to create a Set of some kind (e.g. HashSet) and add all of your items (in your case integers) to that set. If the set has the same size as your original array of items then the items are all unique, if the size differs there are duplicates.
I got this string[] I use in a grid of these images. The grid is generated randomly using a random. now I use the way of just adding the one object more times. but my algorithm to regenerate one if two pictures are the same(eg. egg-tree-blackcar-blackcar-pinkcar) won't work because I check the array indexes of the images.
String bingoObject[] = {
"black_car",
"gray_car",
"white_car",
"red_car",
"yellow_car",
"blue_car",
"pink_car",
"green_car",
"boat",
"tree",
//ADDED MORE FOR CHANCES
"black_car",
"black_car",
"gray_car",
"white_car",
"red_car",
"blue_car",
"green_car"
};
Is there another way to get randoms and assigning probability to each object without having to add them more times into the array? This would clean and help me through a lot of messy coding.
I don't personally know of any ways to assign probability, but we can kind of create our own way. It's not the most efficient way of doing so, but it does create a pseudo-probability.
int [] numbers = {1,2,3,4,5,6,7,8,9,10};
int index = 0;
Random rnd = new Random();
for (int i = 0; i < 3; i ++)
{
index = index + rnd.nextInt(numbers.length);
}
index=index/3;
System.out.println(numbers[index]);
This will skew the array index to be somewhere near the middle, most of the time. So the most common values, in theory, will be near the middle of the array, while the borders will be very uncommon.
You can change the "3" value to be whatever you want, the higher this number is, the more middle-biased the numbers should be.
Upon running this 10 times, my values were:
2,6,7,2,6,5,6,6,4,5
I'm taking a Java class in College. My instructor is actually a teacher for languages derived from C, so she can't figure out what's going on with this piece of code. I read on this page http://docs.oracle.com/javase/6/docs/api/java/util/List.html that I could use the syntax "list[].add(int index, element)" to add specific objects or calculations into specific indexes, which reduced the amount of coding needed. The program I'm looking to create is a random stat generator for D&D, for practice. The method giving the error is below:
//StatGenrator is used with ActionListener
private String StatGenerator ()
{
int finalStat;
String returnStat;
//Creates an empty list.
int[] nums={};
//Adds a random number from 1-6 to each list element.
for (int i; i > 4; i++)
nums[].add(i, dice.random(6)+1); //Marks 'add' with "error: class expected"
//Sorts the list by decending order, then drops the
//lowest number by adding the three highest numbers
//in the list.
Arrays.sort(nums);
finalStat = nums[1] + nums[2] + nums[3];
//Converts the integer into a string to set into a
//texbox.
returnStat = finalStat.toString();
return returnStat;
}
My end goal is to use some kind of sorted list or method of removing the lowest value in a set. The point of this method is to generate 4 random numbers from 1-6, then drop the lowest and add the three highest together. The final number is going to be the text of a textbox, so it is converted to a string and returned. The remainder of the code works correctly, I am only having trouble with this method.
If anyone has any ideas, I'm all ears. I've researched a bit and found something about using ArrayList to make a new List object, but I'm not sure on the syntax for it. As a final note, I tried looking for this syntax in another question, but I couldn't find it anywhere on stackoverflow. Apologies if I missed something, somewhere.
'int nums[]' is not a List, it's an array.
List<Integer> intList = new ArrayList<>();
creates a new ArrayList for example.
You can access Elements in the list directly with the following Syntax :
intList.get(0); // Get the first Element
You can sort Lists with the Collections class :
Collections.sort(intList);
Here are some informations about Collections in Java : http://docs.oracle.com/javase/tutorial/collections/
Arrays are fixed size, so you need to allocate space for all the slots at the start. Then to put numbers into the array assign to nums[i]. No add() method needed.
int[] nums = new int[4];
for (int i = 0; i < 4; i++)
nums[i] = dice.random(6) + 1;
Arrays.sort(nums);
finalStat = nums[1] + nums[2] + nums[3];
Alternatively, if you really want a dynamically-sized array, use an ArrayList. An ArrayList can grow and shrink.
List<Integer> nums = new ArrayList<Integer>();
for (int i = 0; i < 4; i++)
nums.add(dice.random(6) + 1);
Collections.sort(nums);
finalStat = nums.get(1) + nums.get(2) + nums.get(3);
Notice how different the syntax is due to ArrayList being a class rather than a built-in type.
nums[].add(i, dice.random(6)+1); //Marks 'add' with "error: class
expected"
You are trying to use add on an array. List is a dynamic array, but that doesn't mean that array == List. you should use List instead.
List<Integer> nums=new ArrayList<Integer>();
//Adds a random number from 1-6 to each list element.
for (int i; i > 4; i++)
nums.add(i, dice.random(6)+1);
You're mixing arrays and lists.
Have a look at the tutorial:
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
http://docs.oracle.com/javase/tutorial/collections/index.html