Here's the code:
public class Deck {
private Card[] cards;
public Deck() {
cards = new Card[52];
String[] ranks = {"ace","two","three","four","five","six","seven","eight","nine","ten","jack","queen","king"};
String[] suits = {"hearts","diamonds","clubs","spades"};
for(int i = 0; i < suits.length; i++) {
for(int n = 0; n < ranks.length; n++) {
cards[cards.length] = new Card(ranks[i],suits[n]);
}
}
}
}
As you can see, this loops though the two given arrays and generates a card for every combination. There are 13 ranks x 4 suits = 52 cards. I expected that on the 52nd iteration, cards.length would be 51, but the compiler says
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 52
at com.cards.Deck.<init>(Deck.java:14)
Why is that?
The issue is that cards.length is not the total number of elements used in the array; it's the total number of elements in the array, regardless of what you've stored in the array so far. Consequently, as soon as you execute the inner loop, this will try accessing the 52nd element of the array, causing the exception you've seen.
To fix this, consider instead storing a counter that will keep track of the next free index, or use some simple math to derive the position that the card should go in from its suit and value. For example, since on each iteration of the outer loop you will write ranks.length elements to the array, on iteration (i, n) you will write to array index i * ranks.length + n. Using this, you could rewrite the inner loop as
// Careful... still buggy!
for(int i = 0; i < suits.length; i++) {
for(int n = 0; n < ranks.length; n++) {
cards[i * ranks.length + n] = new Card(ranks[i],suits[n]);
}
}
Additionally, note that your access into the arrays is wrong. Right now, you're writing
new Card(ranks[i],suits[n]);
However, i ranges over suits, not values. The proper code would be
new Card(ranks[n],suits[i]);
Which gives this final implementation:
for(int i = 0; i < suits.length; i++) {
for(int n = 0; n < ranks.length; n++) {
cards[i * ranks.length + n] = new Card(ranks[n],suits[i]);
}
}
More generally, though, don't use the .length field of an array to track how many used elements there are. You'll need to store that separately. Alternatively, consider using an ArrayList, which wraps an array and tracks this for you.
Hope this helps!
cards[cards.length]
Because you're trying to use an index that doesn't exist. cards.length is 52, your array is 0 - 51.
I suspect you're trying to insert each card into that array, which means you need another counter ;)
int cardIndex = 0;
for(int i = 0; i < suits.length; i++) {
for(int n = 0; n < ranks.length; n++, cardIndex++) {
cards[cardIndex] = new Card(ranks[n],suits[i]);
}
}
EDIT: What I didn't catch is what others have mentioned - you also have the counters for ranks/suits switched in the Card constructor - fixed that too.
The index variables for ranks ranks and suits are exchanged.
(Don't damage your head with your palm.)
Consider it with renamed variables:
for(int SUIT = 0; SUIT < suits.length; SUIT++) {
for(int RANK = 0; RANK < ranks.length; RANK++) {
cards[cards.length] = new Card(ranks[SUIT],suits[RANK]);
}
}
It isn't always best to use i and n. (I would have used s and r.)
Also, consider:
Card[] cards = new Card[X];
cards[X] // will never be "in bounds", indices from [0, X-1]
Happy coding.
Related
I need to have the columns organized in increasing order. Right now I have the following done but, it is sorting the rows and not columns.Any help would be nice, ive been working on this all day. Thanks.
public static double[][] sortColumns(double[][] m) {
double[][] sortedArray = new double[m.length][m.length];
for (int i = 0; i < m.length; i++) {
double[] temp = new double[m.length];
for (int j = 0; j < m.length; j++) {
temp[j] = m[j][i];
}
Arrays.sort(temp);
for (int j = 0; j < temp.length; j++) {
sortedArray[j][i] = temp[j];
}
}
return sortedArray;
}
If you change
temp[j] = m[j][i];
to
temp[j] = m[i][j];
and
sortedArray[j][i] = temp[j];
to
sortedArray[i][j] = temp[j];
then your existing algorithm will work fine. It just means you'll be copying columns to your "temporary sorting area" instead of rows.
In your current solution, you are just mistaking on indexes, just like David Wallace tells you in his answer. I propose you a different answer, enumerating the possible solutions of this problem.
You have at least 4 solutions :
instead of storing your data like you are currently doing it, use the transponate of your matrix
implement yourself an efficient sorting algorithm that takes a bi-dimensional array and the index of a column in argument
at each turn of you loop, fill an array with the current column, sort it, and copy it back (if you don't care about using some additional memory, do it). That is what you are currently trying to do
transponate your matrix, sort its lines, transponate it back (if you don't want to use too much memory, use this)
I prefer the last solution, which code is :
public static double[][] sortColumns(double[][] m) {
double[][] sortedArray = new double[m.length][m.length];
// compute the transponate of m
for (int i=0 ; i<m.length ; i++)
for (int j=0 ; j<m[i].length ; j++)
sortedArray[j][i] = m[i][j];
// sort the lines of the transponate
for (int i=0; i<sortedArray.length; i++)
Arrays.sort(sortedArray[i]);
// transponate back the result of the sorting
for (int i=0 ; i<sortedArray.length ; i++)
for (int j=i+1 ; j<sortedArray[i].length ; j++) {
double tmp = sortedArray[i][j];
sortedArray[i][j] = sortedArray[j][i];
sortedArray[j][i] = tmp;
}
return sortedArray;
}
When I look at your code I see the following line:
double[][] sortedArray = new double[m.length][m.length];
it doesn't look right to me.
you need to find length and breath of the array so i would do something like this:
length = m.length;
breath = m[0].length;
if i m not sure of all rows have same no of elements i may do that check by a for loop and initialize with the max.. wud lead to memory wastage but thats another demon to tame :)
next when we write m[x][y] x represents the rows and y represents the columns so when ur doing :
for (int j = 0; j < m.length; j++) {
temp[j] = m[j][i];
}
Arrays.sort(temp);
you are fetching all the values from a column i, assigning it to temp array and sorting the column.
hope that helps
So, I have a method like this
public String[][] getArgs(){
And, I want it to get results out of a for loop:
for(int i = 0; i < length; i++){
But how do I append them to the array instead of just returning them?
Create a String[][] array inside your method, fill this array inside a loop (or in any other way) and return that array in the end.
If you are sure you want to have only one for loop (instead of two, typical for 2-dimensional array), ensure your loop will go through the number of examples equal to the number of fields in your String[][] array. Then you can calculate the double-dimension array indexes from your single loop-iterator, for example:
for(int i = 0; i < length; i++){
int a = i % numberOfCollumnsInOutput;
int b = i / numberOfCollumnsInOutput;
String[a][b] = sourceForYourData[i];
}
(Of course which array dimension you treat as collumns (and which to be rows) depends on yourself only.) However, it is much more typical to go through an n-dimensional array using n nested loops, like this (example for 2d array, like the one you want to output):
for(int i = 0; i < dimensionOne; i++){
for(int j = 0; j < dimensionTwo; j++){
array[i][j] = someData;
}
}
For your interest. A sample code according to Byakuya.
public String[][] getArgs(){
int row = 3;
int column =4;
String [][] args = new String[row][column];
for(int i=0;i<row;i++)
for(int j=0;j<column;j++)
args[i][j] = "*";
return args;
}
You can make a LinkedList from that array, and then append the elements to it, and then create a new array from it. If you are not sure i'll post some code.
I have the code below:
int lines = 0;
while(lines < 2)
{
int[] oldarr = parr;
for(int i = 0; i < arrsize; i++)
System.out.print(" " + oldarr[i]);
System.out.println();
for(int i = 0; i < arrsize; i++)
{
if(i == 0)
parr[i] = 0;
else
parr[i] = Math.abs(oldarr[i] - oldarr[i-1]);
}
lines++;
}
parr is an array of integers of size [arrsize]. Each time through this loop I want to print the value of each index in parr, then set each index to the difference between the index before it and itself. Currently it gives me the correct (hardcoded) originally parr. But the next(first) iteration of changing parr gives me unexpected values; they are not even close to the difference between the two neighboring values..
Any ideas?
You aren't copying your array with this line:
int[] oldarr = parr;
The two variables are still pointing at the same array.
To get a copy, you can do:
int[] oldarr = Arrays.copyOf(parr, parr.length);
In your second for loop, you are setting the new value to the difference of the current value and the previous value, but the previous value was already changed in the previous iteration of the for loop.
Change your second for loop iteration to iterate through the array backwards, so your calculations don't depend on previous calculations.
for(int i = arrsize - 1; i >= 0; i--)
I'm trying to create a 2D array of lists for a Sudoku. Essentially 81 lists each containing possible solutions to that box in the Sudoku grid. I've tried multiple declarations so far, but whenever I try to add values to a list it returns a null pointer exception. Here is an example, simply populating each of the lists with the numbers 1-9.
List<Integer>[][] sudoku = (List<Integer>[][]) new List[9][9];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
for (int k = 1; k < 10; ) {
sudoku[i][j].add(k);
}
}
}
I'm not even positive a 2D array of lists is the optimal way to go about this, but I've done everything from scratch (with a relatively low knowledge of java) so far so I'd like to follow through with this method. The original code looked as follows:
List[][] sudoku = new List[9][9];
Research quickly revealed that this wouldn't cut it.
Thank you in advanced for any help!
Try this one. The general idea, create a master list and while you loop through it, create one inner list.
/* Declare your intended size. */
int mainGridSize = 81;
int innerGridSize = 9;
/* Your master grid. */
List<List<Integer>> mainList = new ArrayList<List<Integer>>(mainGridSize);
/* Your inner grid */
List<Integer> innerList = null;
/* Loop around the mastergrid */
for (int i=0; i<mainGridSize; i++) {
/* create one inner grid for each iteration of the main grid */
innerList = new ArrayList<Integer>(innerGridSize);
/* populate your inner grid */
for (int j=0; j<innerGridSize; j++)
innerList.add(j);
/* add it to your main list */
mainList.add(innerList);
}
Illustrated:
If you need to vary your grid, just change the values of the gridSize.
You cannot create array of generic lists.
You can create List of Lists:
List<List<List<Integer>>> soduko = new ArrayList<>();
And then populate it as you wish.
or use casting:
List[][] soduko = (List<IntegerNode>[][]) new LinkedList[9][9];
You have create the array of Lists but you did not initialize it. Insert this in the second line an the problem should be solved.
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++){
sudoku[i][j]=new ArrayList<Integer>();
}
}
Or to do it all in one go do it like this:
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
sudoku[i][j]= new ArrayList<Integer>();
for (int k = 1; k < 10; ) {
sudoku[i][j].add(k);
}
}
}
If you know that you need exactly 81 2D arrays, you can create 3D array:
int[][][] sudoku = new int[81][9][9];
The way you did it now would produce compilation error.
I have the following code to set 10 random values to true in a boolean[][]:
bommaker = new boolean[10][10];
int a = 0;
int b = 0;
for (int i=0; i<=9; i++) {
a = randomizer.nextInt(9);
b = randomizer.nextInt(9);
bommaker[a][b] = true;
}
However, with this code, it is possible to have the same value generated, and therefore have less then 10 values set to random. I need to build in a checker, if the value isn't already taken. And if it is already taken, then it needs to redo the randomizing. But I have no idea how to do that. Can someone help me?
simplest solution, not the best:
for (int i=0; i<=9; i++) {
do {
a = randomizer.nextInt(10);
b = randomizer.nextInt(10);
} while (bommaker[a][b]);
bommaker[a][b] = true;
}
You're problem is similar to drawing cards at random from a deck if I'm not mistaken...
But first... The following:
randomizer.nextInt(9)
will not do what you want because it shall return an integer between [0..8] included (instead of [0..9]).
Here's Jeff's take on the subject of shuffling:
http://www.codinghorror.com/blog/2007/12/shuffling.html
To pick x spot at random, you could shuffle your 100 spot and keep the first 10 spots.
Now of course seen that you'll have only 10% of all the spots taken, simply retrying if a spot is already taken is going to work too in reasonable time.
But if you were to pick, say, 50 spots out of 100, then shuffling a list from [0..99] and keeping the 50 first value would be best.
For example here's how you could code it in Java (now if speed is an issue you'd use an array of primitives and a shuffle on the primitives array):
List<Integer> l = new ArrayList<Integer>();
for (int i = 0; i < 100; i++) {
l.add(i);
}
Collections.shuffle(l);
for (int i = 0; i < n; i++) {
a[l.get(i)/10][l.get(i)%10] = true;
}