Java Math.random with arrays - java

I am trying to populate my 2d array that is 5 by 5 with a char such as A in random coordinates in the 2d array. When I use my nested for loop i wanted to make the coordinates of the 2d array where my char will be to be random. So lets say I asked for 40 percent of A's, in a 5 by 5 I should get 10 A's but I get 8. When i run it, it doesn't show the percentage of A's i wanted sometimes. it would only print out like 6. Is this because when the row and col in the if statement are randomized, so is the row and col in the for loop? Is this why the char sometimes populates less then asked for because the for loop stops if the number randomizes the length of the 2d array which is 5?
Also when it does print out 10 char, sometimes they go over the 5 by 5. an example would be 2 As in the line and 7 in the second and 1 in the 3rd. Why is that?
public static void grid(char[][] arr, int percentofchar)
{
double charx = 0.0;
double totalpercentchar = 0;
totalpercentchar = (double) percentofchar / 100;
cellx = totalpercentchar * (arr.length * arr.length);
for (int row = 0; row < arr.length; row++)
{
for (int col = 0; col < arr[row].length; col++)
{
if (charx > 0)
{
row = (int) (Math.random() * arr.length);
col = (int) (Math.random() * arr.length);
charx--;
arr[row][col] = 'A';
System.out.print(arr[row][col] + " ");
}
}
System.out.println();
}
}

your code should be something like
public static void grid(char[][] array, int percentOfChar)
{
int charsToPlace = (int) (percentOfChar * array.length * array.length / 100.0);
while (charsToPlace > 0)
{
int row = (int) (Math.random() * array.length);
int column = (int) (Math.random() * array.length);
if (array[row][column] != 'A');
{
array[row][column] = 'A';
charsToPlace--;
System.out.print(array[row][column] + " ");
}
}
System.out.println();
}
No need to loop through the array and to use nested loop if you are only trying to insert a char in a random position.
Also
Is this because when the row and col in the if statement are
randomized, so is the row and col in the for loop? Is this why the char sometimes populates
less then asked for because the for loop stops if the number
randomizes the length of the 2d array which is 5? Also when it does print out 10 char,
sometimes they go over the 5 by 5. an example would be 2 As in the
line and 7 in the second and 1 in the 3rd. Why is that?
More or less. You randomize row and column, but in doing so it could lead to a premature end of the iteration through the array. As a worst case scenario, consider what happens if the first time you enter the if statement the random functions assign the 4 values to both row and col. In general, are you sure that at the end of the grid method charx will always be equals to 0?
Considerations
As Matt pointed out in the below comments, this method has no check on the array; so, it assumes that the array is always a square one (i.e. row X column = n X n).
If you want to force the use of a square array, you may want to create a wrapper class, e.g.
class IntegerSquareArray
{
public final int length;
int[][] array;
IntegerSquareArray(int length)
{
this.length = length;
this.array = new int[length][length];
}
public int getValue(int row, int column)
{
if (row < length && column < length)
return array[row][column];
throw new IllegalArgumentException();
}
public void setValue(int row, int column, int value)
{
if (row < length && column < length)
array[row][column] = value;
else throw new IllegalArgumentException();
}
}
Then, you can simply change the grid code to be
public static void grid3(IntegerSquareArray integerSquareArray,
int percentOfChar)
{
int charsToPlace = (int) (percentOfChar * integerSquareArray.length
* integerSquareArray.length / 100.0);
while (charsToPlace > 0)
{
int row = (int) (Math.random() * integerSquareArray.length);
int column = (int) (Math.random() * integerSquareArray.length);
if (integerSquareArray.getValue(row, column) != 'A')
{
integerSquareArray.setValue(row, column, 'A');
charsToPlace--;
System.out.print(integerSquareArray.getValue(row, column) + " ");
}
}
System.out.println();
}

Just for completeness, here is what I mentioned in the comments under tigerjack's solution. As per the comments, I would use a wrapper for the grid rather than a raw multidimensional array.
My random placement solution is a little bit more complicated, but it will be much more efficient for higher placement percentages (ie. if you're trying to fill greater than 90% of the cells) and will always fill the exactly specified percent of characters.
If desired, you could use tigerjack's method for random placements when percentOfCellsToSet is lower, and this method when percentOfCellsToSet is higher using an if statement in the setRandomCells() method.
Here is my complete compileable example using the shuffled list method:
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MyGrid
{
private int width;
private int height;
private char[][] grid;
public MyGrid(int width, int height, char defaultCell)
{
this.width = width;
this.height = height;
grid = new char[height][width];
// populate grid with defaultCells:
for(int x=0; x < width; ++x)
{
for(int y=0; y < height; ++y)
{
grid[y][x] = defaultCell;
}
}
}
public int getWidth() { return width; }
public int getHeight() { return height; }
public char getCell(int x, int y) { return grid[y][x]; }
public void setCell(int x, int y, char cellValue) { grid[y][x] = cellValue; }
public void setRandomCells(char cellValue, float percentOfCellsToSet)
{
// determine the number of cells to set (rounding to nearest int):
int numCellsToSet = (int)(Math.round((width * height * percentOfCellsToSet) / 100.0));
// create a list containing all possible cell positions:
List<Point> listAllCellLocations = new ArrayList<>();
for(int x=0; x < width; ++x)
{
for(int y=0; y < height; ++y)
{
listAllCellLocations.add(new Point(x,y));
}
}
// shuffle it
Collections.shuffle(listAllCellLocations);
// now set the cells
for(int i=0; i < numCellsToSet; ++i)
{
Point pt = listAllCellLocations.get(i);
setCell(pt.x, pt.y, cellValue);
}
}
public void debugPrintGrid()
{
for(int y=0; y < height; ++y)
{
for(int x=0; x < width; ++x)
{
System.out.print(getCell(x,y));
}
System.out.println();
}
}
public static void main(String[] args)
{
MyGrid myGrid = new MyGrid(10, 10, '0');
myGrid.setRandomCells('A', 68);
myGrid.debugPrintGrid();
}
}
and here is the sample output from the code in the main() method:
AAAA0A0AAA
0AAAAAAAA0
A00A00AA0A
AAAAA0AAA0
AA0A0AAAA0
0A0AAAA0AA
A0AAA0A0AA
A0A00AAAAA
AAA000A0A0
0AA0AAA0A0
Hope someone finds this helpful.

You assign random values to the cycle variables... Now this is as undeterministic as it could be...
Basically your nested loops will end if by any chance the first Math.random() results in arr.length - 1 and the 2nd results in arr[arr.length - 1].length -1.
I seriously doubt this is what you wanted.
To control how many random As to put into the array, just use a loop for that but don't assign random values to the cycle variable:
int max = arr.length * arr.length * percentofchar / 100;
for (int i = 0; i < max; i++) {
// Put `A` at a random location
int row = (int) (Math.random() * arr.length);
int col = (int) (Math.random() * arr.length);
arr[row][col] = 'A';
System.out.print(arr[row][col] + " ");
}
Also note that this still might result in less A than the percent would mean because the same random location might be generated multiple times, so the same array element might be set to A multiple times.
If you want to generate exact count of As, you have to retry if the random location is already an A:
int max = arr.length * arr.length * percentofchar / 100;
for (int i = 0; i < max; i++) {
// Put `A` at a random location
int row, col;
do {
row = (int) (Math.random() * arr.length);
col = (int) (Math.random() * arr.length);
} while (arr[row][col] == 'A');
arr[row][col] = 'A';
System.out.print(arr[row][col] + " ");
}

Your code places "A"s randomly, so some "A" may placed on same place.
Let calculate possibility to see 10 "A"s as result.
First "A" is always empty place, so you see 1 "A" at 100%
For placing second "A", there are 1 place occupied by "A" and 24 empty place, so you see 2 "A" after placing second "A" at 96%. (Second A may placed where first "A" placed in possibility 1 out of 25(4%).
For third, possibility is (24/25) * (23/25).
... omitted in 4th to 9th .
For 10th, you see 10 "A"s in possibility of (24/25)(23/25)(22/25)(21/25)(20/25)(19/25)(18/25)(17/25)(16/25). (The value is about 12.4%)
This calculation says that you code may show 10 "A"s in result about once by eight.

Related

Return a zigzag array

I have two questions:
public static int[] everyOther(int[] arr)
Given an integer array arr, create and return a new array that contains precisely the elements in the even-numbered positions in the array arr. Make sure that your method works correctly for arrays of both odd and even lengths, and for arrays that contain zero or only one element. The length of the result array that you return must be exactly right so that there are no extra zeros at the end of the array.
public static int[][] createZigZag(int rows, int cols, int start)
This method creates and returns a new two-dimensional integer array, which in Java is really just a one-dimensional array whose elements are one-dimensional arrays of type int[]. The returned array must have the correct number of rows that each have exactly cols columns. This array must contain the numbers start, start + 1, ..., start + (rows * cols - 1) in its rows in order, except that the elements in each odd-numbered row must be listed in descending order.
For example, when called with rows = 4, cols = 5 and start = 4, this method should create and return the two-dimensional array whose contents are
4 5 6 7 8
13 12 11 10 9
14 15 16 17 18
23 22 21 20 19
when displayed in the traditional matrix form that is more readable for the human than the more realistic form of a one-dimensional array whose elements are one-dimensional arrays of rows.
public static int[] everyOther(int[] arr){
for (int i = 0 ; i < aList.size() ; i+=2)
{
return( aList.get(i) + " ") ;
}
}
public static int[][] createZigZag(int rows, int cols, int start){
{
int evenRow = 0;
int oddRow = 1;
while (evenRow < rows)
{
for (int i = 0; i < cols; i++)
{
return(start[evenRow][i] + " ");
}
evenRow = evenRow + 2;
if(oddRow < rows)
{
for (int i = cols - 1; i >= 0; i--)
{
return(start[oddRow][i] + " ");
}
}
oddRow = oddRow + 2;
}
}
}
does this make sense?
Try this as an attempted solution to your exercise.
Notes:
If you copy paste this whole code, make sure your class file is named TestExample as is this one.
Inside main method are just some tests so that you see the output printed and you can verify it. You can ignore Arrays.toString(), it's just to print the int[] arrays to the screen in a better format.
Wherever you see final, you can ignore it or erase it (for now, that you still learn the language). In a simple first look, it means you don't intend to change this variable. After you proceed in learning the language, visit this again but this time consider that it "locks" the variable name to a specific reference inside the enclosing scope. It doesn't guarantee immutability of the value however except if it is a primitive value (int, long, float, double etc).
Notice that the arrays have to have been initialized (their dimensions) before you assign any value to a specific position of the array.
For the everyOther method, note that Java is zero-based in its indexing and thus in the array new int[] { 8, 9, 10, 11 }; your first odd-indexed value is 9 and the second is 11.
General advice: If you are now starting with a language, use an IDE like Eclipse (it's free & open source), IntelliJ (free) or NetBeans(free & open source). It would red-underline the errors in your code and (if configured) display warning messages as well for dangerous practices.
Code:
import java.util.Arrays;
public class TestExample
{
public static int[][] createZigZag(final int rows, final int cols, int start)
{
final int[][] array = new int[rows][cols];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
array[i][j] = start;
start++;
}
}
return array;
}
public static int[] everyOther(final int[] array)
{
int otherArrayLength;
if (array.length % 2 == 0)
{
otherArrayLength = array.length / 2;
}
else
{
otherArrayLength = array.length / 2 + 1;
}
final int[] otherArray = new int[otherArrayLength];
int count = 0;
for (int i = 0; i < array.length; i += 2)
{
otherArray[count] = i;
count++;
}
return otherArray;
}
public static void main(final String[] args)
{
final int[] testArray = new int[] { 0, 1, 2, 3, 4, 5, 6 };
final int[] everyOtherArray = everyOther(testArray);
System.out.println(Arrays.toString(everyOtherArray));
final int rows = 4;
final int cols = 5;
final int start = 4;
final int[][] zigzagArray = createZigZag(rows, cols, start);
for (int i = 0; i < rows; i++)
{
System.out.println(Arrays.toString(zigzagArray[i]));
}
}
}

DFS Algorithm - 8-Puzzle or nXn-Game

I want to solve an DFS algorithm. It is about the game 8-puzzles or N x N puzzle. At the beginning i have two arrays like (the Zero represents an empty field):
int[][] start = {{0,1,2}, {4,5,3}, {7,8,6}};
int[][] target = {{1,2,3}, {1,5,6}, {7,8,0}};
This arrays goes into my generic DFS class, which works fine. I used it of other tasks correctly. But for the completeness here is the basic part of my DFS class:
private static boolean search(State node, State target) {
if (node.equals(target))
return true;
for (State neighbour : node.getNeighbours()) {
if (!visited.contains(neighbour)) {
predMap.put(neighbour,node);
visited.add(neighbour);
if (search(neighbour, target)){
return true;
}
}
}
return false;
}
So at first my start array will pass as the first parameter and my target array as the second.
In my Stateclass i want to implement the getNeighbours()method which should return all possibles states. In the first Round something like:
First:
|0|1|2|
|4|5|3|
|7|8|6|
Second (rotated zero):
|1|0|2|
|4|5|3|
|7|8|6|
etc...
And here is my problem. How can u do that? It works for the first 4 operations but then i get an exception (The zero or the empty field is not on the position as excepted or there are two zeros). What is wrong there?
#Override
public List<State> getNeighbours() {
List<State> neighbours = new LinkedList<>();
// possibles moves...
final int startX = (freeX - 1 < 0) ? freeX : freeX - 1;
final int startY = (freeY - 1 < 0) ? freeY : freeY - 1;
final int endX = (freeX + 1 > N - 1) ? freeX : freeX + 1;
final int endY = (freeY + 1 > N - 1) ? freeY : freeY + 1;
for (int row = startX; row <= endX; row++) {
for (int column = startY; column <= endY; column++) {
int tmp = board[row][column];
board[row][column] = board[freeX][freeY];
board[freeX][freeY] = tmp;
// Just show the table...
System.out.println("=== BEFORE ===");
for (int[] x : board) {
System.out.println(Arrays.toString(x));
}
neighbours.add(new State(board, freeX + row, freeY + column));
board[freeX][freeY] = board[row][column];
board[row][column] = tmp;
// Just show the table...
System.out.println("=== AFTER ===");
for (int[] x : board) {
System.out.println(Arrays.toString(x));
}
}
}
return neighbours;
}
complete code https://gist.github.com/T0bbes/66d36326aa8878d5961880ce370ba82d
I checked your code, the reason of get that exception is, the board array is shared by every state. You should make a deep copy of that array, and you can try this code:
public Board(int[][] board, int x, int y){
if (board[x][y]!=0)
throw new IllegalArgumentException("Field (" +x+","+y+") must be free (0).");
this.board = new int[board.length][board[0].length];
for (int i = 0; i < this.board.length; i++)
for (int j = 0; j < this.board[i].length; j++)
this.board[i][j] = board[i][j];
this.freeX = x;
this.freeY = y;
this.N = board.length;
}
But there are still some problems in your code:
DFS may recursion a lot and get a StackOverflow -- you should increase stack size(-Xss100m works for me). After increase stack size, your code can output a solution, but it takes 197144 steps...
Indeed, as you see, DFS output only a valid solution(if your code is correct), not optimal solution. You should try BFS.

write 0's and 1's on each line where the last 2 weren't the same

There's an error in the logic of what I've build at the moment.
What should be happening is that my code should display a grid of 0's and 1's.
Like so:
001001
101101
010110
110010
001101
So what has to happen here is that:
For each row there can't be more than 2 numbers of the same type consecutively
the numbers are picked randomly
for each column there can't be more than 2 numbers of the same type consecutively
there can be a maximum of 3 of each type of number going by column or row
edit: to further clarify
ok so I have a row like this:
0 1 0 1 1 0
- As you can see there will always be 3 x 1, and 3 x 0
- the order of numbers is picked randomly (so it might go 0 1, or 1 1, or 0 0 to start etc)
- there can never be more than 2 numbers of the same type consecutively, for instance if it's 001100, you can see that there were 2 0's, then it had to display a 1, but then there were 2 1's, so it had to display an 0. So 011100 couldn't happen (3 1's consecutively) or 000101 (3 0's consecutively)
Based upon this, but for now not essential, the same no 2 numbers consecutively must apply in columns (so in my successful example it goes 001001 across, there are at most 2 0's consecutively. But looking down you get 010101 (that is to say, once again, no more than 2 consecutively)
So my code is as follows:
import java.util.Random;
public class Main {
public static void main(String[] args) {
int l = 6;
int w = 6;
Random rd = new Random();
// Create a grid that is 6 x 6
int[][] grid = new int[l][w];
// for each row
for (int i = 0; i < l; i++) {
int zCount = 0;
int oCount = 0;
int current;
int lastA = 2;
int lastB = 2;
// for each item in the row
for (int j = 0; j < w; j++) {
// set the current item to either 0 or 1
current = rd.nextInt(2);
// make sure there aren't already (e.g. 3 items out of 6)
// items in the row
if (j % 2 == 1) {
// hold every second element
lastA = current;
} else {
// hold every first element
lastB = current;
}
if (current == 1) {
if (oCount != 3) {
if (lastA != lastB) {
// if the two previous items aren't the same
grid[i][j] = current;
// add to the counter
oCount++;
}
}
}
if (current == 0) {
if (zCount != 3) {
if (lastA != lastB) {
// if the two previous items aren't the same
grid[i][j] = current;
// add to the counter
zCount++;
}
}
}
System.out.print(grid[i][j]);
}
System.out.println(" ");
}
}
}
The problem is it generates as follows:
010010
100001
100010
000010
100001
001000
So obviously it doesn't conform to the first, third or fourth points.
I have absolutely no idea why! Except for the columns (third point) which I haven't initialised.
Can anybody work out what the logical failure is in my code?
Thanks for your help!
Here is my procedural solution which tries to keep the amount of required code as small as possible. It is capable of computing 2D-Arrays with arbitrary rows and columns like [6, 6] or [4, 7] or [3, 8] for example. The complexity of the algorithm is O(n) with n = rows * columns.
The program computes an arbitrary 2D-Array (grid) populated with either a 0 or 1. The grid guarantees the following characteristics, formulated mathematically:
∀ r,c ∈ Integer | 0 ≤ r < grid.rows, 0 ≤ c < grid.columns :
r - 2 ≥ 0 ⇒ cardinality( distinct( grid[r][c], grid[r-1][c], grid[r-2][c] )) = 2
r + 2 < grid.rows ⇒ cardinality( distinct( grid[r][c], grid[r+1][c], grid[r+2][c] )) = 2
c - 2 ≥ 0 ⇒ cardinality( distinct( grid[r][c], grid[r][c-1], grid[r][c-2] )) = 2
c + 2 < grid.columns ⇒ cardinality( distinct( grid[r][c], grid[r][c+1], grid[r][c+2] )) = 2
or in other words:
the grid does neither contain a row nor a column which has three or more consecutive 0's or 1's.
Below the Java code I will explain how the algorithm works and why it is designed as it is:
public static void main(String[] args) {
int[][] grid = anyGrid(8, 13);
}
private static int[][] anyGrid(int rows, int cols) {
int[][] grid = new int[rows][cols];
int row = 0;
for (int col = 0; col - row < cols; col++) {
for (int r = row; r >= 0 && col - r < cols;) {
setBit(grid, r, col - r--);
}
if (row < rows - 1) row++;
}
return grid;
}
private static void setBit(int[][] grid, int row, int col) {
int vInd = calcVerticalIndicator(grid, row, col);
int hInd = calcHorizontalIndicator(grid, row, col);
if (isPartiallyRestricted(vInd, hInd)) {
grid[row][col] = flip(vInd);
} else if (isFullyRestricted(vInd, hInd)) {
grid[row][col] = vInd;
grid[row - 1][col] = flip(vInd);
} else {
grid[row][col] = Math.abs(vInd) <= 1
? flip(vInd)
: Math.abs(hInd) <= 1 ? flip(hInd) : anyBit();
}
}
private static boolean isPartiallyRestricted(int vInd, int hInd) {
return vInd == hInd;
}
private static boolean isFullyRestricted(int vInd, int hInd) {
return vInd + hInd == 1;
}
private static int calcVerticalIndicator(int[][] grid, int row, int col) {
return calcIndicator(grid, row - 1, col, row - 2, col, 2);
}
private static int calcHorizontalIndicator(int[][] grid, int row, int col) {
return calcIndicator(grid, row, col - 1, row, col - 2, 4);
}
private static int calcIndicator(int[][] grid, int row1, int col1, int row2, int col2, int unrestricted) {
try {
return grid[row1][col1] * grid[row2][col2] + (grid[row1][col1] - grid[row2][col2]) * unrestricted;
} catch (IndexOutOfBoundsException e) {
return unrestricted;
}
}
private static int anyBit() {
return (int) (Math.random() * 2);
}
private static int flip(int bit) {
return bit == 0 ? 1 : 0;
}
The challenge we face is not to ensure that there are no three consecutive 0's or 1's in a row only or in a column only. The challenge is to ensure that no three consecutive 0's or 1's are neither in a row nor in a column by providing an efficient algorithm.
The tricky situation we may run into looks like this:
Let's consider the situation where all the cells at the top and to the left of the cell outlined in blue are already populated and do not violate the rules define above.
picture a) we want to populate the cell having a blue outline. The two cells at it's top are populated with two 0's while the cells at it's left are populated with two 1's. Which value should we choose? Due to symmetry it doesn't matter if we choose a 0 or a 1. Hence, let's go with a 0.
picture b) populating the cell outlined in blue with a 0 violates one rule defined above: the grid does not contain a column with three or more consecutive 0's or 1's. Hence we have to change the value of one of the two cells above of the blue cell.
picture c) say we change the value of the cell which is immediately above the blue cell, from 0 to 1. This could result in the violation of some rules, caused by the already populated cells to the left of the modified cell.
picture d) but a violation would mean that both cells to the left must have a value of 1.
picture e) this would imply that both cells to their top must have a value of 0 which is a contradiction to a situation we assumed. Therefore, changing the cell immediately at the top of the cell outlined in blue will not cause any violation of the rules.
To address the precondition, that no cells to the right of the modified cell are already populated, the algorithm populates the grid in a diagonal way. The population of cells occur in the order as shown below:
The final thing I like to explain is how the algorithm decides which values are available to choose from for each cell. For each cell it inspects the two top-most and two left-most cells and calculates an indication value. This value is used to determine the possible values for a cell by using arithmetic calculation as follows:
if the two cells inspected are both populated with 0's return an indicator value of 0.
if the two cells inspected are both populated with 1's return an indicator value of 1.
I have selected those two values because they communicate the fact, that this values are not permitted, in an intuitive way.
Then I selected a function to communicate if both, the column cells and the row cells, restrict the cell to populate by the same value. This is the case if both indicator values are equal. Keep this characteristic in mind, because we have to find values for the situation when no restriction applies from the column cells or the row cells.
If both indicators restrict the value to populate the cell with by a different value, the sum of them is 1. This is the second characteristic we have to keep in mind when searching for proper indicator values when no restriction applies.
The last thing the algorithm has to achieve is to find proper values when no restriction applies without compromising the unique indicators defined above.
Preserving the indication when the cell is restricted by the same value can be achieved by selecting values for the row and column indicators which are different from 0 and 1 and different from each other.
Preserving the indication when the cell is restricted by both values can be achieved by selecting values being greater than 1 and having a delta to each other of at least 2.
The algorithm does indicate no restriction for a row by the values 2 and -2 and for a column by the values 4 and -4. This values do not conflict with the operations used to identify the other two cases.
I hope this documentation helps to understand the whole program and how it does solve the problem statement. I am glad to hear your comments.
Many of the solutions given are extremely long and complicated. Here's a solution with very minimal code (Ideone Example here):
int row, col, n = 8;
int[][] grid = new int[n][n], cCount = new int[n][2], rCount = new int[n][2];
Deque<Entry<Integer,Integer>> freeInd = new ArrayDeque<Entry<Integer,Integer>>();
Random rand=new Random();
for(int i = 0; i < grid.length; i++){
for(int j = 0; j < grid[0].length; j++){
// Calcualte constraints: row, col = {-1, 0, 1}, -1 => no constraint.
row = j > 1 && grid[i][j-2] == grid[i][j-1] ? (grid[i][j-1] == 0 ? 1:0):
(rCount[i][0] >= n/2 ? 1: // too many 0's
(rCount[i][1] >= n/2 ? 0:-1)); // too many 1's
col = i > 1 && grid[i-2][j] == grid[i-1][j] ? (grid[i-1][j] == 0 ? 1:0):
(cCount[j][0] >= n/2 ? 1: // too many 0's
(cCount[j][1] >= n/2 ? 0:-1)); // too many 1's
grid[i][j] = row == -1 && col == -1 ? rand.nextInt(2):(row > -1 ? row:col);
// Handle Constraints
if( row == -1 && col == -1){ // no constraint
freeInd.push(new SimpleEntry<Integer,Integer>(i, j)); // add to free indices
} else if( (row > -1 && col > -1 && row != col) // constraint conflict
|| (row > -1 && rCount[i][row] >= n/2) // count conflict
|| (col > -1 && cCount[j][col] >= n/2)){ // count conflict
Entry<Integer, Integer> last = freeInd.pop(); // grab last free index
while(i > last.getKey() || j > last.getValue()){
j = (j-1+ n)%n; // step indices back
i = (j == n-1) ? i-1:i;
rCount[i][grid[i][j]]--; // reduce counters
cCount[j][grid[i][j]]--;
}
grid[i][j] = grid[i][j] == 0 ? 1:0; // flip value
}
rCount[i][grid[i][j]]++; // increment counters
cCount[j][grid[i][j]]++;
}
}
The idea here is that you walk along each row of the matrix adding 0's and 1's abiding by the following rules:
If the current index is unconstrained (i.e. it can be 0 or 1) we choose a value randomly.
If the current index is constrained we force it to have the constrained value.
If there are multiple constraints that do not agree, we revert back to the last unconstrained index (freeInd) by first incrementally stepping backwards along the rows of the matrix, decrementing the count for the given value (0 or 1). E.g. this is done for rows with rCount[i][grid[i][j]]--. When the unconstrained vertex is finally reached, flip it's value.
Finally, increment the count of the value (0 or 1) for the current row and column. E.g. this is done for rows with rCount[i][grid[i][j]]++
The 1st problem which i found in your solution is it's initializing the value of counter value (ocount and zcount) as zero and the only way grid(array) is assigned a value is when if it's greater than three, and the way i see if i am not mistaken the value of counter is incremented in the loop in which they are checked to be greater than 3, and that condition can never be reached .
To solve this problem use the algo of backtracking by assigning the new value to a different value if the calue
A working code in jsFiddle (for 6x6 grids):
$(function(){
function print(str){
$("body").append(str + "<br/>");
}
function toBin(num, length){
if(!length){
length = 3;
}
var str = num.toString(2);
while(str.length < length){
str = 0 + str;
}
return str;
}
var wrongAnds = [
parseInt('000000111', 2),
parseInt('000111000', 2),
parseInt('111000000', 2),
parseInt('100100100', 2),
parseInt('010010010', 2),
parseInt('001001001', 2),
];
var wrongOrs = [
parseInt('111111000', 2),
parseInt('111000111', 2),
parseInt('000111111', 2),
parseInt('011011011', 2),
parseInt('101101101', 2),
parseInt('110110110', 2),
];
function test(mask){
for (var i = 0; i < 6; i++) {
if((wrongAnds[i] & mask) == wrongAnds[i]){
return false;
}
if((wrongOrs[i] | mask) == wrongOrs[i]){
return false;
}
}
return true;
}
var threeGrid = [];
var toRight = [];
var toBottom = [];
for(var mask = 1<<9-1; mask >= 0; mask--){
if(test(mask)){
threeGrid.push(mask);
}
}
function numberOfSetBits(i)
{
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}
function getCol(grid, col){
var ret = 0;
for(var i=0; i<3; i++){
ret += (grid & (1 << (i*3+col))) >> (i*2+col);
}
return ret;
}
var wrongAnds6 = [
parseInt('011100', 2),
parseInt('001110', 2)
];
var wrongOrs6 = [
parseInt('100011', 2),
parseInt('110001', 2)
];
for(var i = 0; i < threeGrid.length; i++){
for(var j = 0; j < threeGrid.length; j++){
var grid1 = threeGrid[i];
var grid2 = threeGrid[j];
var toRightOk = true;
var toBottomOk = true;
var printit = (i==0);
for(var k=0;k<3;k++){
var row = ((grid1 & wrongAnds[k]) << 3 >> (k*3)) + ((grid2 & wrongAnds[k]) >> (k*3));
var col = ((getCol(grid1, k)) << 3) + ((getCol(grid2, k)));
if(numberOfSetBits(row) != 3
|| ((wrongAnds6[0] & row) == wrongAnds6[0])
|| ((wrongAnds6[1] & row) == wrongAnds6[1])
|| ((wrongOrs6[0] | row) == wrongOrs6[0])
|| ((wrongOrs6[1] | row) == wrongOrs6[1])
) {
toRightOk = false;
}
if(numberOfSetBits(col) != 3
|| ((wrongAnds6[0] & col) == wrongAnds6[0])
|| ((wrongAnds6[1] & col) == wrongAnds6[1])
|| ((wrongOrs6[0] | col) == wrongOrs6[0])
|| ((wrongOrs6[1] | col) == wrongOrs6[1])
) {
toBottomOk = false;
}
}
if(toRightOk){
if(!toRight[grid1]){
toRight[grid1] = [];
}
toRight[grid1].push(grid2);
}
if(toBottomOk){
if(!toBottom[grid1]){
toBottom[grid1] = [];
}
toBottom[grid1].push(grid2);
}
}
}
function intersect(arr1, arr2){
var results = [];
for (var i = 0; i < arr1.length; i++) {
if (arr2.indexOf(arr1[i]) !== -1) {
results.push(arr1[i]);
}
}
return results;
}
var found = false;
while(!found){
var grid1 = threeGrid[0];
var grid1 = threeGrid[Math.floor(Math.random()*threeGrid.length)];
var grid2 = toRight[grid1][Math.floor(Math.random()*toRight[grid1].length)];
var grid3 = toBottom[grid1][Math.floor(Math.random()*toBottom[grid1].length)];
var arr4 = intersect(toBottom[grid2], toRight[grid3]);
if(arr4.length > 0){
var grid4 = arr4[Math.floor(Math.random()*arr4.length)];
found = true;
}
}
function gridToStrings(grid){
var rowS = [];
for(var i=0; i<3; i++){
rowS.push(toBin(((grid & wrongAnds[i]) >> (i*3))));
}
return rowS;
}
var grid1S = gridToStrings(grid1);
var grid2S = gridToStrings(grid2);
var grid3S = gridToStrings(grid3);
var grid4S = gridToStrings(grid4);
print(grid1S[0] + grid2S[0]);
print(grid1S[1] + grid2S[1]);
print(grid1S[2] + grid2S[2]);
print(grid3S[0] + grid4S[0]);
print(grid3S[1] + grid4S[1]);
print(grid3S[2] + grid4S[2]);
});
Theory:
Find all possible 3x3 grids
Find all possible left-to-right and top-to-bottom pairings
get 4 random grids to form the 6x6 grid
Implementation:
Represent 3x3 grids as 9bit integers. A 3x3 grid is wrong if there are 3 1s or 3 0s in it. This can be easily filtered with a couple bitwise operations.
Test the Cartesian product of these 3x3 grids (Compare every grid with every grid). Check if there are exactly 3 0s and 3 1s in all rows and columns (put the second grid right to the first grid to check 3 rows, and put it below the first grid to check 3 columns), and that there are no consecutive 3 0s or 1s.
get the top-left, top-right and bottom-right grids. Check if there is an available 4th grid that can go below the top-right grid and right to the bottom-left grid. If there is none, restart step 4, otherwise pick one.
A couple outputs:
011010
100101
001011
110100
101100
010011
110010
101100
010011
001101
100110
011001
001101
110010
010011
101100
110100
001011
Edit:
there is only 1120 solutions to this problem (jsFiddle). There are 2^36 ways to fill a 6x6 grid with 0s and 1s. If you used brute force (get a random 6x6 grid, then check if its right), that would mean an average ~61356676 (6.1*10^7) executions to find a correct solution. Even thought your method is somewhat faster (it can fail sooner if its not the last digit thats wrong), it might still be slow.
I think there are two problems with your code:
If oCount or zCount have become 3 there are no more assignments grid[i][j]=current if the random value is not acceptable. You get zeroes at these positions (to which the grid was initialized).
Near the right bottom there might not be any more valid solutions. You would have to undo previous assignments, i.e. you would need to do some kind of backtracking.
I would recommend starting with a valid solution and transforming this solution step by step according to random values for grid positions - but only if this is possible without breaking validity. If have prepared an example implementation:
public static void main(String[] args) {
int l = 6, w = 6;
Grid g = new Grid(l, w);
Random rd = new Random();
// initialize with checkerboard pattern (which is a valid solution)
for (int y = 0; y < l; y++) for (int x = 0; x < w; x++) g.arr[y][x] = (x ^ y) & 1;
// construct a valid grid by transformation of grids while preserving validity
for (int y = 0; y < l; y++) for (int x = 0; x < w; x++) {
int v = rd.nextInt(2), v2 = v ^ 1;
if (g.arr[y][x] == v) continue;
// try to modify current grid by exchanging values: 01/10=>10/01 or 10/01=>01/10
// (keep parts of the grid which have already been adapted to random values)
rotating: for (int y2 = y + 1; y2 < l; y2++) for (int x2 = x; x2 < w; x2++) {
if (g.arr[y2][x] == v && g.arr[y][x2] == v && g.arr[y2][x2] == v2) {
g.rotate(x, y, x2, y2);
// keep result if grid is still valid, undo otherwise
if (g.rotatedOk(x, y, x2, y2)) break rotating;
g.rotate(x, y, x2, y2);
}
}
}
g.printOn(System.out);
}
public static class Grid {
int l, w;
int[][] arr;
Grid(int l, int w) {
this.arr = new int[this.l = l][this.w = w];
}
void rotate(int x, int y, int x2, int y2) {
int v;
v = arr[y][x]; arr[y][x] = arr[y2][x]; arr[y2][x] = v;
v = arr[y][x2]; arr[y][x2] = arr[y2][x2]; arr[y2][x2] = v;
}
boolean rotatedOk(int x, int y, int x2, int y2) { // check after rotation
return okAt(x, y) && okAt(x2, y) && okAt(x, y2) && okAt(x2, y2);
}
private boolean okAt(int x, int y) { // check single position in grid
int v = arr[y][x];
if (count(x, y, -1, 0, v) + count(x, y, 1, 0, v) > 1) return false;
if (count(x, y, 0, -1, v) + count(x, y, 0, 1, v) > 1) return false;
return true;
}
private int count(int x, int y, int dx, int dy, int v) {
for (int n = 0; ; n++) {
x += dx; y += dy;
if (x < 0 || x >= w || y < 0 || y >= l || arr[y][x] != v) return n;
}
}
void printOn(PrintStream s) {
for (int y = 0; y < l; y++) { for (int x = 0; x < w; x++) s.print(arr[y][x]); s.println(); }
}
}
The problem with your approach is that you need a mechanism that handles when a new value can't be used because it follows two similar values, but the other value can't be used because it is under two other values. For example, say your grid has got this far:
101010
011010
00?
You would then need to slowly roll back positions and try different values.
The following code solves that problem using recursion:
import java.util.Random;
public class Main {
final int height = 6;
final int width = 6;
int[][] grid;
Random rd = new Random();
public static void main(final String[] args) {
Main main = new Main();
main.process();
}
private void process() {
// Create a grid that is 6 x 6
grid = new int[height][width];
for(int x = 0; x < width; x++) {
for(int y = 0; y < height; y++) {
grid[x][y] = -1;
}
}
recurseFillMatrix(0, 0);
}
private boolean recurseFillMatrix(final int x, final int y) {
// first, try putting a random number in the cell
int attempt = 1;
grid[x][y] = Math.abs(rd.nextInt()%2);
do {
if(isGridValid()) {
if(x == (width - 1) && y == (height - 1)) {
printGrid();
return true;
}
boolean problemSolved;
if(x == (width - 1)) {
problemSolved = recurseFillMatrix(0, y + 1);
} else {
problemSolved = recurseFillMatrix(x + 1, y);
}
if(problemSolved) {
return true;
}
}
attempt++;
grid[x][y] = 1 - grid[x][y];
} while(attempt <= 2);
grid[x][y] = -1;
return false;
}
private boolean isGridValid() {
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
// if the current item is -1, then we are finished
if(grid[x][y] == -1) {
return true;
}
// if we are after the second column
if(x > 1) {
if(grid[x-2][y] == grid[x-1][y] && grid[x-1][y] == grid[x][y]) {
return false;
}
}
// if we are after the second row
if(y > 1) {
if(grid[x][y-2] == grid[x][y-1] && grid[x][y-1] == grid[x][y]) {
return false;
}
}
// total the values in this column
int total = 0;
for(int i = 0; i <= y; i++) {
total += grid[x][i];
}
if(y == (height - 1)) {
if(total != 3) {
return false;
}
} else {
if(total > 3) {
return false;
}
}
// total the values in this row
total = 0;
for(int i = 0; i <= x; i++) {
total += grid[i][y];
}
if(x == (width - 1)) {
if(total != 3) {
return false;
}
} else {
if(total > 3) {
return false;
}
}
}
}
return true;
}
private void printGrid() {
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
System.out.print(grid[x][y]);
}
System.out.println("");
}
}
}
The isGridValid() method uses your defined rules to check if the grid (as it is filled so far) complies with the rules. At the first sign that it does not, it returns false.
If I have to change your solution to achieve the result, here is what it should look like..
Take the incrementors for oCount and zCount in a separate if-else
Take the assignment to grid(i,j) outside the loop
Your if-else block is not taking into account every condition possible, like
What about when last 2 items are same
What about when the zCount or oCount has reached 3
Taking into account these consideration, this code works fine.
import java.util.Random;
public class Main {
public static void main(String[] args) {
int l = 6;
int w = 6;
Random rd = new Random();
// Create a grid that is 6 x 6
int[][] grid = new int[l][w];
// for each row
for (int i = 0; i < l; i++) {
int zCount = 0;
int oCount = 0;
int current;
int lastA = 2;
int lastB = 2;
// for each item in the row
for (int j = 0; j < w; j++) {
// set the current item to either 0 or 1
current = rd.nextInt(2);
// make sure there aren't already (e.g. 3 items out of 6)
// items in the row
if (current == 1) {
if (oCount != 3) {
if (lastA == lastB) {
current = lastA == 1 ? 0 : 1;
}
} else {
current = current == 1 ? 0 : 1;
}
} else if (current == 0) {
if (zCount != 3) {
if (lastA == lastB) {
current = lastA == 1 ? 0 : 1;
}
} else {
current = current == 1 ? 0 : 1;
}
}
grid[i][j] = current;
if (current == 1) {
oCount++;
} else {
zCount++;
}
if (j % 2 == 1) {
// hold every second element
lastA = current;
} else {
// hold every first element
lastB = current;
}
System.out.print(grid[i][j]);
}
System.out.println(" ");
}
}
}
Again, This solution takes care of row conditions only. You would need to do similar checks for columns as well, to achieve the full result
HTH
here I tested you problem and seems that it is what you need.
I used a functional approach using Guava, it is quite simple, readable and has a short code.
#Test
public void test_permutations()
{
List<Integer> binary = Lists.newArrayList(1,0,1,0,1,0); // Domain list
Set<String> flattenSet = Sets.newHashSet(); // Store non-repetitive values
// Create list of possible values
Collection<List<Integer>> permutations = Collections2.permutations(binary);
for (List<Integer> permutation : permutations)
{
String joinString = StringUtils.join(permutation, "");
flattenSet.add(joinString);
}
// Create predicate to filter positive values
Predicate<String> predicate = new Predicate<String>() {
public boolean apply(String input) {
// Discard wrong values
if (input.contains("000") || input.contains("111")) {
return false;
} else {
return true;
}
}
};
// Use predicate to filter values
Collection<String> filteredList = Collections2.filter(flattenSet, predicate);
// Display result
for (String result : filteredList) {
System.out.println(result);
}
}
It is simple, I've commented the code to be clear but you can debug it to understand step by step.
The generated output is:
010011
110010
010101
010110
100110
101001
011010
110100
001011
001101
011001
101010
101100
100101
Hope to help
I think that its a mistake to think of generating it one element at at time. Instead imagine that I generate the entire set of permissible rows {001100,101010,....etc} There are only 6!/(3!3!)=20 ways to arrange three ones and three and some of them will be excluded. Now I am going to generate a game tree by saying that a move is selecting a valid row for the next row. If I discover at some point that there are no more valid moves then i will back track and try a different move.
To generate a move I randomly select a row, if its a valid move, I try to select another move, if that is impossible I backtrack, effectively doing a (random) depth first search of the game tree.
public class gametree {
public static ImmutableList<Row> allValidRows = // create a list of all valid rows.
public static List<Rows> getValidMoves(Move parent){ //Backtracks up the
//tree to the root to find the current state of the board, and returns
//which ever of allValidRows are valid given the game board.
}
public class Move {
public final Move parent;
public List<Rows> validMoves;
public final Row thisMove;
public int depth=0;
Move(Move parent, Row thisMove){
this.thisMove = thisMove;
this.parent = parent;
this.validMoves = getValidMoves(parent);
Move hold=parent;
while(hold!=null){
depth++; hold = parent.parent;
}
}
}
void run {
//pick first move
Move Root = new Move(null, Collections.Shuffle(allValidRows).get(0));
Move FinalMove = search(Root);
//Something to print out the answer here
}
public Move search(Move move){
if(depth==5){ return Move} //If I get to row six I win.
else if(move.validMoves.isEmpty()) { //If there are no valid moves,
//then this move wasnt valid, to strip it from the parent's
//possible moves and try again
move.parent.validMoves.remove(move.thisMove);
search(move.parent);
} else { //pick a random valid move and create a nextMove
Move nextMove = new Move(move, Collection.Shuffle(move.getValidMoves).get(0))
search(nextMove);
}
}
The worst case for this algorithm is that there is only one victory state and it has to try every possible state, but in practice this game does not seem very restrictive so it will probably not take long at all.
This code is strictly illustrative.

Need to work on an array recursively, trouble passing data, java

Ok, I am having a really beginner mistake here, but I can't think of what I need to do. I have an array permArray that I am recursively filling with possible permutations. I have a public method that gets the parameters ready, then I work on the array in the private method that calls itself to work on smaller and smaller parts.
The problem I am having, is how do I pass the finished array back to the public method. Would I return the array every time I am finished with the recursion (after I have placed the last element in each section, where the section size is 1).
Oh, and also, this is practice, not homework.
//todo:
//need to determine what is wrong with my array of linked lists
package wordchains;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import java.util.StringTokenizer;
import javax.xml.soap.Node;
/**
*
* #author Samuel French
*/
public class WordChains {
public static void main(String[] args) {
//variables
int numWords = -1; //This will hold the number of words the user is inputting
String userInput; //holds the user input to be broken up into a string array
//Get the user's input, 0 is the quit value
Scanner sc = new Scanner(System.in);
System.out.print("Enter number of words: ");
numWords = sc.nextInt();
System.out.println(">");
sc.nextLine();
userInput = sc.nextLine();
String[] inputWords = userInput.split("\\s+");
int numElements = inputWords.length;
int numOfPerms = numOfPerms(numElements);
//We will start by checking the last letter of the first word
char cTest;
int wordChecking = 0;
int[][] permArray = genPerms(numElements, numOfPerms);
for (int col = 0; col < numOfPerms; col++) {
System.out.println();
for (int row = 0; row < numElements; row++) {
System.out.print(permArray[col][row] + " ");
}
}
}
public static int numOfPerms(int numElements) {
int numOfPerms = numElements;
numElements--;
while (numElements > 0) {
numOfPerms = numOfPerms * numElements;
System.out.println(numOfPerms);
numElements--;
}
return numOfPerms;
}
public static int[][] genPerms(int numElements, int totPerms) {
int permArray[][] = new int[totPerms][numElements];
//either do it like this or create an array of head nodes
List<LinkedList<Integer>> elementsLeftList = new ArrayList<LinkedList<Integer>>();
LinkedList tempList = new LinkedList();
for (int x = 0; x < numElements; x++) {
tempList.addLast(x);
}
for (int x = 0; x < totPerms; x++) {
elementsLeftList.add((LinkedList<Integer>) tempList.clone());
}
return privateGenPerms(permArray,elementsLeftList,totPerms,0,0,totPerms);
}
private static void privateGenPerms(int[][] permArray, List<LinkedList<Integer>> elementsLeftList, int totalPermutations, int elementPlacing, int sectionBegin, int sectionSize) {
//variables-
//totalPermutations - the total number of permutations in the whole problem
//elementPlacing - the element currently being placed's position, corresponds to the rows of permArray
//elementPlacingIndex - the number of times the element currently being placed has been placed
//sectionSize - the size of the total working section. First time this is the # of permutations
//permCounter - this counter counts the permutation working with within the section
//sectionBegin - counts the beginning of the section working with
//2 Data structures:
//permArray - 2d the array of permutations
//elementsLeftList - list of lists of elements left, corresponds to each permutation
int totalNumberOfElements = permArray[0].length;
//
int numberOfElementsLeftToPlace = totalNumberOfElements - elementPlacing;
//
int permCounter = sectionBegin;
//Base case
if (numberOfElementsLeftToPlace == 1) {
for (int x = 0; x < totalPermutations; x++) {
permArray[x][totalNumberOfElements - 1] = (int) elementsLeftList.get(permCounter).remove(0); //may need to be a remove 1, not sure
}
return; //need to decide what I am going to do here
}
//
int elementPlacingIndex = 0;
int elementCurrentlyPlacing = 0; //could be a 1, don't remember
//
int numberOfTimesToPlaceWithinCol = (sectionSize / numberOfElementsLeftToPlace);
//
//
for (; permCounter < (sectionBegin + sectionSize); permCounter++) {
//when we need to switch to a different partition of the section
if (elementPlacingIndex == numberOfTimesToPlaceWithinCol) {
elementPlacingIndex = 0;
elementCurrentlyPlacing++;
}
permArray[permCounter][elementPlacing] = (int) elementsLeftList.get(permCounter).remove(elementCurrentlyPlacing);
elementPlacingIndex++;
}
for (int newSectionBegin = sectionBegin; newSectionBegin < (sectionBegin + sectionSize); newSectionBegin = newSectionBegin + numberOfTimesToPlaceWithinCol) {
privateGenPerms(permArray, elementsLeftList, totalPermutations, (elementPlacing + 1), newSectionBegin, (sectionSize / numberOfElementsLeftToPlace));
}
}
}
The array is passed-by-reference, so any changes you make in the private function will be permanent and you do not need to return the modified array again.
I have not looked at your logic to see if this is the correct way to do it in your case though.

Java 2D array error

So I need to take a 2D array do calculations to each elements and transfer that into another 2D array while using the values to the "left" "right" "up" and "down" of the current element. If the current element is on the edge (x = 0, y = 0, x = array.length , y = array.length) I will get an array out of bounds error. I want to create a for loop that deals with each of those cases but I don't know how to do it. A sample of my code is
private void buildE(int[][] array, int y, int x)
{
int up = array[y - 1][x];
int down = array[y + 1][x];
int left = array[y][x - 1];
int right = array[y][x + 1];
if(up == 0){
buildETopRow(array);
}
E will be my new array. This method does not work because y does not equal 0, it just doesn't exist but I can't set ints to null either. In the case of an out of bounds error I need the element (up, down, left, or right) that is out of bounds to equal the current element. Is there a way I can still use a for loop for this or do I need to do something else?
If I read this correctly you want to effectively treat the difference of an element on the edge with an element off the edge as 0. If that's true I would write four methods right(), left(), up() and down(), with down() shown below as an example:
/*
* Return the difference between an element an the element below it
*/
public void down(int x, int y) {
if (y == array.length - 1) {
\\ on the bottom edge
return 0;
}
return array[y][x] - array[y + 1][x];
}
And inside your loop you'd calculate:
up(x,y) + down(x,y) + right(x,y) + left(x,y)
or whatever calculation it is you need to sum up.
The easiest way it to surround your array with a border region. So that your x dimension is really width+2.
import java.util.*;
import java.lang.*;
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
int realWidth = 10;
int realHeight = 10;
int[][] in = new int[(realWidth+2)][(realHeight+2)];
int[][] out = new int[(realWidth+2)][(realHeight+2)];
for (int j = 1;j<realHeight+1;j++)
{
for (int i = 1;i<realWidth+1;i++)
{
int top = in[j-1][i];
int bottom = in[j+1][i];
int left= in[j][i-1];
int right = in[j][i+1];
out[j][i] = operation(top,bottom,left,right);
}
}
}
public static int operation (int top,int bottom,int left,int right)
{
return top+bottom+left+right;
}
}
I'm not totally sure what your question is, but (1) the usual structure for traversing a 2D array is to use nested for loops (one inside the other), and (2) when you want wrap-around counters (e.g. 2, 3, 0, 1, 2, ...) use the remainder operator %.
int numRows = theArray.length;
int numCols = theArray[0].length;
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numCols; j++) {
int right = theArray[(j+1) % numCols];
int down = theArray[(i+1) % numRows];
int left = theArray[(j+numCols-1) % numCols];
int up = theArray[(i+numRows-1) % numCols];
/* right, down, left, and up will be the elements to the right, down,
left, and up of the current element. Npw that you have them, you can
process them however you like and put them in the other array. */
}
}
What the remainder operator A%B does is sets A back to zero once it gets as large as B. Since B is the size of your array, that's exactly when it is too large and will cause an IndexOutOfBounds error. Note: That's not how % works but it's an ok way to think of what it does. To find out more about it you can google it, I found an ok explanation here.

Categories