change the same numbers in a matrix recursively - java

given a matrix of int numbers, a row and col indexs (for a random cell that contains a number) and a new number, I need to recursively return the matrix- however now with all of the surrounding cells that matched the random cell number to the new one. for example:
for the following matrix-
4,1,2,2
4,4,3,1
1,4,4,4
1,4,0,2
called by fill(grid,1,1,0),
this one needs to be returned:
* 0 1 2 2
0 0 3 1
1 0 0 0
1 0 0 2
what I tried is the following
public static int[][] fill(int[][] grid, int i, int j, int needed ) {
if (i<= grid.length - 1 && j<=grid[0].length - 1 && i>0 && j>0) {
grid[i][j] = needed ;
if(legal_Neighbor(grid,i,j, i+1,j))
grid= fill(grid, i+1,j,needed );
if(legal_Neighbor(grid,i,j, i,j+1))
grid= fill(grid, i,j+1,needed );
if(legal_Neighbor(grid,i,j, i,j-1))
grid= fill(grid, i,j-1,needed );
if(legal_Neighbor(grid,i,j, i-1, j))
grid= fill(grid, i-1,j,needed );
}
where legal_Neighbor is a function I'm calling that's checking if both cells have the same number and are next to each other
been stuck on this for a couple of days. would love for some help

If I understand your question correctly, you want to propagate the needed value to neighbors with equal value to origin.
the point here, is to make each node in the grid acts like a automaton, to pass the value to the neighbor if itself gets changed.
following is the code, but i left boundaryCheck blank:
static int[][] fill(int[][] grid, int i, int j, int needed) {
if (!boundaryCheck()) throw new RuntimeException();
int[][] clone = new int[grid.length][grid[0].length];
//Clone matrix grid
for (int k = 0; k < clone.length; k++) {
clone[k] = grid[k].clone();
}
propagate(clone, i, j, needed, grid[i][j]);
return clone;
}
static void propagate(int[][] grid, int i, int j, int needed, int target) {
if (!boundaryCheck() || grid[i][j] != target || needed == target) return;
grid[i][j] = needed;
propagate(grid, i+1, j, needed, target);
propagate(grid, i-1, j, needed, target);
propagate(grid, i, j+1, needed, target);
propagate(grid, i, j-1, needed, target);
}

Related

Problem with a Java program that counts number of non self-intersecting paths between upper left to bottom right of a square array

It is well known that when one is allowed only to move right and down, the number of paths between the upper left cell to the bottom right cell of a rectanglular grid with side lengths n,m is the binomial coefficient n+m on n. I tried to think, at first in a mathematical manner, about the number of such paths when one is also allowed to move left and up; obviously the only way to give meaningful answer to such a question is to count non self-intersecting paths that do not go outside the rectangle (without those restrictions, the number of paths is infinite)
Since I had no idea how to count the number of such paths combinatorially, I wrote a java program that counts such paths and prints the paths, which I restricted to square arrays. However, already in an array of size 3x3, the program prints only 9 paths, while checking the number of such paths manually gave 12 paths. Here is the program:
public class pathCalculator {
public static int pathsCalculator(boolean[][] arr) {
return pathsCalculator(arr, 0, 0, "");
}
public static int pathsCalculator(boolean[][] arr, int i, int j, String s) {
if (i < 0 || i > arr.length - 1 || j < 0 || j > arr[0].length - 1) {
return 0;
} else if (arr[i][j] == false) {
return 0;
}
if (i == arr.length - 1 && j == arr[0].length - 1) {
s = s + "[" + (arr.length - 1) + "," + (arr.length - 1) + "]";
System.out.println(s);
return 1;
} else {
arr[i][j] = false;
s = s + "[" + i + "," + j + "]";
boolean[][] arr1 = new boolean[arr.length][arr.length];
for (int n = 0; n <= arr.length - 1; n++) {
for (int m = 0; m <= arr.length - 1; m++) {
arr1[n][m] = arr[n][m];
}
}
return pathsCalculator(arr1, i + 1, j, s) + pathsCalculator(arr1, i - 1, j, s) + pathsCalculator(arr1, i, j + 1, s) + pathsCalculator(arr1, i, j - 1, s);
}
}
}
The boolean array that is checked is initialized in the main program to be a square of "true"'s.
The main ideas of the program are therefore:
Recursion - each time the method calls to four variations of itself, which correspond to the four possibilies of: moving down,up,right and left.
Flagging forbidden cells - each time the path approaches a given cell, the program changes the cell's boolean value from true to false. The second if condition causes the program to return 0 in case we arrived at a forbidden cell (this indicates the path is self-intersecting).
Creating copies of the original boolean array - to prevent the different paths from interacting with each other on the same board, in each recursive step the previous boolean array values are copied into a new array.
So what is the problem with what I wrote? why it counts only a part of the total number of paths?
A minor change in the program, but of critical importance, enables the program to return the correct number of non self-intersecting paths bewteen the upper left cell to bottom right cell. In the coping part of the code, just before the recursive call, one should initialize 4 arrays instead of one, each of which is an identical copy of the previous array, and then let each of the four calls of pathscalculator method continue with a different copy of the array.
Here is the corrected version of the program:
public class pathCalculator{
public static int pathsCalculator(boolean[][] arr)
{
return pathsCalculator(arr,0,0,"");
}
public static int pathsCalculator(boolean [][] arr, int i, int j,String s)
{
if(i<0||i>arr.length-1||j<0||j>arr[0].length-1)
{
return 0;
}
else if(arr[i][j]==false)
{
return 0;
}
if(i==arr.length-1&&j==arr[0].length-1)
{
s = s+"["+(arr.length-1)+","+(arr.length-1)+"]";
System.out.println(s);
return 1;
}
else
{
arr[i][j]=false;
s = s+"["+i+","+j+"]";
boolean[][] arr1 = new boolean[arr.length][arr.length];
boolean[][] arr2 = new boolean[arr.length][arr.length];
boolean[][] arr3 = new boolean[arr.length][arr.length];
boolean[][] arr4 = new boolean[arr.length][arr.length];
for(int n=0;n<=arr.length-1;n++){
for(int m=0;m<=arr.length-1;m++){
arr1[n][m]=arr[n][m];
arr2[n][m]=arr[n][m];
arr3[n][m]=arr[n][m];
arr4[n][m]=arr[n][m];
}
}
return pathsCalculator(arr1,i+1,j,s)+pathsCalculator(arr2,i-1,j,s)+pathsCalculator(arr3,i,j+1,s)+pathsCalculator(arr4,i,j-1,s);
}
}
}
Here is the main function:
public class pathCalculatorTester
{
public static void main(String[] args)
{
boolean[][] arr ={{true,true,true},{true,true,true}
,{true,true,true}};
System.out.println(pathCalculator.pathsCalculator(arr));
}
}
And this is the output:
[0,0][1,0][2,0][2,1][1,1][0,1][0,2][1,2][2,2]
[0,0][1,0][2,0][2,1][1,1][1,2][2,2]
[0,0][1,0][2,0][2,1][2,2]
[0,0][1,0][1,1][2,1][2,2]
[0,0][1,0][1,1][0,1][0,2][1,2][2,2]
[0,0][1,0][1,1][1,2][2,2]
[0,0][0,1][1,1][2,1][2,2]
[0,0][0,1][1,1][1,2][2,2]
[0,0][0,1][1,1][1,0][2,0][2,1][2,2]
[0,0][0,1][0,2][1,2][2,2]
[0,0][0,1][0,2][1,2][1,1][2,1][2,2]
[0,0][0,1][0,2][1,2][1,1][1,0][2,0][2,1][2,2]
12
It returns the correct number of paths for 3x3 square, but since I don't have full understanding why it was nessecary to initialize 4 arrays insted of one, I'm not sure it works well for larger arrays. By the way, the function f(n) where n is the length size of the square and f is the number of paths, appears to grow amazingly fast - for 4x4 squares the number of paths that the program returned is 184, and for 5x5 squares the number is 8512.

Knights tour problem with an irregular chessboard

the knights tour problem is a problem based on backtracking. In the normal version you have a N*N chessboard and you have to visit every single field on the board with your knight. But here comes the real problem: I can visit every field only once! So if i have no more fields to visit, i have to backtrack. At the end of your game, the number of fields should equals the number of movements. Now to my different version: I'm not working with a N*N chessboard, but with an irregular one. For example: The first row has 5 fields, the second one has 3, and the third one 8. These information are given me by a boolean array. There are also "false" fields that are not allowed to visit. I'm not allowed to change the boolean array.
public static boolean checkboard(boolean[][] board) {
for (int i0 = 0; i0 < board.length; i0++) {
boolean[] dim1 = board[i0];
if (dim1 == null) {
return false;
} if (board.length == 1) {
return false;
}
}
return true;
}
This is the first part of my code. It checks if the board (boolean array) is valid. That means it should give me false if at least one row is null or if there are no rows.
public static boolean checkPoint(boolean[][] board, int i, int j) {
try {
boolean test = board[i][j];
} catch (IndexOutOfBoundsException a) {
return false;
}
return true;
}
This method checks if the point is in the array.
public static boolean isValid(int i, int j, int[][] sol, boolean[][] board) {
if (i >= 0 && j >= 0 && sol[i][j] == -1 && board[i][j] != false && checkPoint(board,i,j)) {
return true;
}
return false;
}
Here are now some additional information: In the end i want an int array called "sol" that has the same chessboard like my boolean array "board". But in sol I save the number of movements. If there is an false in board, there has to be a 0 in sol. Here is an example of the sol array:
public static boolean springtour(int[][] sol, int i, int j, int step_count, int[] x_move, int[] y_move, boolean[][] board) {
int counter = 0;
for (int row = 0; row < sol.length; row++) {
for (int col = 0; col < sol[row].length; col++) {
if (board[row][col] == true) {
counter++;
}
}
}
if (step_count == counter) {
return true;
}
for(int k=0; k<8; k++) {
int nextI = i+x_move[k];
int nextJ = j+y_move[k];
if (isValid(nextI, nextJ, sol, board)) {
sol[nextI][nextJ] = step_count;
if (springtour(sol, nextI, nextJ, step_count+1, x_move, y_move,board)) {
return true;
}
sol[nextI][nextJ] = -1;
}
}
return false;
}
So now here happens the backtracking. There is a maximum of 8 possible moves from a cell (i, j). Thus, I will make 2 arrays so that we can use them to check for the possible moves (called x_move and y_move). Thus if I am on a cell (i, j), I can iterate over these arrays to find the possible move i.e., (i+2, j+1), (i+1, j+2), etc. My next task is to move to the next possible knight's move and check if this will lead me to the solution. If not, then I will select the different move and if none of the moves are leading me to the solution, then I will return false.
public static int[][] solve(boolean[][] board, int startRow, int startCol) throws IllegalArgumentException {
if (checkboard(board) == false || checkPoint(board,startRow, startCol) == false) {
throw new IllegalArgumentException();
}
int[][] sol = new int[board.length][];
for (int i = 0 ; i < board.length; i++) {
sol[i] = new int[board[i].length];
}
for (int row = 0; row < sol.length; row++) {
for (int col = 0; col < sol[row].length; col++) {
if (board[row][col] == false) {
sol[row][col] = 0;
}
else {
sol[row][col] = -1;
}
}
}
int[] x_move = new int[]{2, 1, -1, -2, -2, -1, 1, 2};
int[] y_move = new int[]{1, 2, 2, 1, -1, -2, -2, -1};
sol[startRow][startCol] = 1;
if(springtour(sol, startRow, startCol,1,x_move,y_move, board)) {
return sol;
}
return null;
}
Now to the last one. Here i will return the sol array. At first i check is there is everything fine with my board and the starting point of the knight. Then i create a sol array and fill it with -1 (or 0 if board is false). Then i have these two arrays with the possible moves x_move and y_move. I set the starting point to 1 and i call my method springtour to do the backtracking. If nothing works it returns null.
My code is not working. There is an ArrayIndexOutOfBoundsException. Can someone help me with this? Maybe i have some other mistakes here. Thank you for helping!
You don't check if the array indices are too high in isValid.
Also your statement "the knights tour problem is a problem based on backtracking" is wrong. Code which attempts to solve a knights tour problem may use backtracking, but there is nothing in the problem definition (find a Hamiltonian path between two given nodes in a class of graphs) which requires that backtracking must be used. You could, for example, use a genetic algorithm, simulated annealing or just keep picking random paths until one works.

An efficient way to get and store the shortest paths

When I say efficient I mean code that isn't cpu intensive.
The Problem:
I have a field of blocks. Like in the following image:
Every single one of these blocks represents an instance of a self-made Block class. This block class has a List<Block> neighBours, where the neighbours of the block are stored. So every single block in the image knows which blocks are next to it.
What I want to do is to pick any block from this image, and compute how many "steps" away this block is. For example if I pick the block in the top left, I want to have a Map<Block, Integer> representing how many "steps" away each block is from the picked block. Like this:
Now before you say "Just store it's position X and Y in the block class and calculate the difference X + difference Y", that wouldn't work because the field can have gaps(represented by red color) between them like the following image:
And as you might notice, the block next to the gap that was first 4 steps away, is now 6 steps away. Thus the best way(I presume) to get how many steps away the other blocks are is by using a recursive algorith that makes use of the neighbour info. I couldn't make an efficient one myself and I was hoping someone might know something that works well.
Several problems I came across are the fact that because all blocks know their neighbours, the recursive algorithm would go indefinately back and forth between the first and second block. Or the fact that when using the algorithm on a 11x11 field, there were 3284 method calls, which seems waaay too high for an 11x11 field.
Question:
So the question I have is: What is an efficient way, using the knowledge of what neighbours each block has, to get how many steps away each block is.
Code:
This is the current code that I have incase anyone wants to see it.
public class Block
{
List<Block> neighBours;
public Block(List<Block> neighBours)
{
this.neighBours = neighBours;
}
public Map<Block, Integer> getStepsAway()
{
Map<Block, Integer> path = new HashMap<Block, Integer>();
getPaths(path, 0, 100);
return path;
}
public void getPaths(Map<Block, Integer> path, int pathNumber, int maxPathNumber)
{
if(pathNumber <= maxPathNumber)
{
for(Block block : neighBours)
{
Integer thePathNumber = path.get(block);
if(thePathNumber != null)
{
if(pathNumber < thePathNumber)
{
path.put(block, pathNumber);
block.getPaths(path, pathNumber + 1, maxPathNumber);
}
}
else
{
path.put(block, pathNumber);
block.getPaths(path, pathNumber + 1, maxPathNumber);
}
}
}
}
}
Recursive algorithms are doomed to fail on a large grid. Java is not designed for deep recursions and can only withstand a few thousands recursive calls before failing with a StackOverflowException. Only iterative solutions are a reasonible approach for large pathfinding problems in Java.
Of course you can always use a classic pathfinding algorithm such as A*, but you would have to apply it for each cell, which would be extremely expensive.
Indeed, your problem is a bit particular in the sense you want to calculate the minimum distance to all cells and not only just one. Therefore, you can do it in a more clever way.
One property of your problem is that given A and B, if the minimal path from A to B contains C then this path is also minimal from A to C and from C to B. That's what my intuition tells me, but it would need to be proven before implementing my suggestion.
The algorithm I propose is efficient, uses O(n) memory and has O(n^2) runtime complexity (cannot be faster since you need to set this many cells in the array):
start with your first point and set the distance of all its valid neighbours to 1. Doing so, you will record the border, which is all the cells at distance 1 from the first cell.
then, you iterate over the border and take all their neighbours which have not already been assigned a distance and assign them distance 2. All cells of distance 2 become your new border.
iterate until the border is empty
Below is a full working solution. The code may be improved in various ways using more convenience methods for initializing and printing matrices of objects and primitive integers, but you get the idea:
public class Solution {
public enum Cell { FREE, BLOCKED }
// assuming cells is a rectangular array with non-empty columns
public static int[][] distances(Cell[][] cells, ArrayCoordinate startingPoint) {
int[][] distances = new int[cells.length][cells[0].length];
// -1 will mean that the cell is unreachable from the startingPoint
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[0].length; j++) {
distances[i][j] = -1;
}
}
distances[startingPoint.i][startingPoint.j] = 0;
Set<ArrayCoordinate> border = startingPoint.validNeighbours(cells);
for (int currentDistance = 1; !border.isEmpty(); currentDistance++) {
Set<ArrayCoordinate> newBorder = new HashSet<>();
for (ArrayCoordinate coord : border) {
distances[coord.i][coord.j] = currentDistance;
for (ArrayCoordinate neighbour : coord.validNeighbours(cells)) {
if (distances[neighbour.i][neighbour.j] < 0) {
newBorder.add(neighbour);
}
}
}
border = newBorder;
}
return distances;
}
private static class ArrayCoordinate {
public ArrayCoordinate(int i, int j) {
if (i < 0 || j < 0) throw new IllegalArgumentException("Array coordinates must be positive");
this.i = i;
this.j = j;
}
public final int i, j;
public Set<ArrayCoordinate> validNeighbours(Cell[][] cells) {
Set<ArrayCoordinate> neighbours = new HashSet<>();
// inlining for not doing extra work in a loop iterating over (-1, 1) x (-1, 1). If diagonals are allowed
// then switch for using a loop
addIfValid(cells, neighbours, 1, 0);
addIfValid(cells, neighbours, -1, 0);
addIfValid(cells, neighbours, 0, 1);
addIfValid(cells, neighbours, 0, -1);
return neighbours;
}
private void addIfValid(Cell[][] cells, Set<ArrayCoordinate> neighbours, int dx, int dy) {
int x = i + dx, y = j + dy;
if (0 <= x && 0 <= y && x < cells.length && y < cells[0].length && cells[x][y] == Cell.FREE) {
neighbours.add(new ArrayCoordinate(i + dx, j + dy));
}
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ArrayCoordinate point = (ArrayCoordinate) o;
if (i != point.i) return false;
if (j != point.j) return false;
return true;
}
#Override
public int hashCode() {
int result = i;
result = 31 * result + j;
return result;
}
}
public static void main(String[] args) {
int n = 11, m = 5;
Cell[][] cells = new Cell[n][m];
cells[1][1] = Cell.BLOCKED;
cells[1][2] = Cell.BLOCKED;
cells[2][1] = Cell.BLOCKED;
ArrayCoordinate startingPoint = new ArrayCoordinate(5, 2);
System.out.println("Initial matrix:");
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[0].length; j++) {
if (cells[i][j] == null) {
cells[i][j] = Cell.FREE;
}
if (startingPoint.i == i && startingPoint.j == j) {
System.out.print("S ");
} else {
System.out.print(cells[i][j] == Cell.FREE ? ". " : "X ");
}
}
System.out.println();
}
int[][] distances = distances(cells, startingPoint);
System.out.println("\nDistances from starting point:");
for (int i = 0; i < distances.length; i++) {
for (int j = 0; j < distances[0].length; j++) {
System.out.print((distances[i][j] < 0 ? "X" : distances[i][j]) + " ");
}
System.out.println();
}
}
}
Output:
Initial matrix:
. . . . .
. X X . .
. X . . .
. . . . .
. . . . .
. . S . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Distances from starting point:
7 8 7 6 7
6 X X 5 6
5 X 3 4 5
4 3 2 3 4
3 2 1 2 3
2 1 0 1 2
3 2 1 2 3
4 3 2 3 4
5 4 3 4 5
6 5 4 5 6
7 6 5 6 7
Bonus
I almost cried when I saw all this boilerplate in my Java solution, so I wrote a shorter (perhaps slightly less efficient) version in Scala:
object ScalaSolution {
sealed abstract class Cell
object Free extends Cell
object Blocked extends Cell
// assuming cells is a rectangular array with non-empty columns
def distances(cells: Array[Array[Cell]], startingPoint: (Int, Int)) = {
// -1 will mean that the cell is unreachable from the startingPoint
val distances = Array.fill[Int](cells.length, cells(0).length)(-1)
distances(startingPoint._1)(startingPoint._2) = 0
var (currentDistance, border) = (1, validNeighbours(cells, startingPoint))
while (border.nonEmpty) {
border.foreach { case (i, j) => distances(i)(j) = currentDistance }
border = border.flatMap(validNeighbours(cells, _)).filter { case (i, j) => distances(i)(j) < 0 }
currentDistance += 1
}
distances
}
private def validNeighbours(cells: Array[Array[Cell]], startingPoint: (Int, Int)) = {
// inlining for not doing extra work in a for yield iterating over (-1, 1) x (-1, 1). If diagonals are allowed
// then switch for using a for yield
Set(neighbourIfValid(cells, startingPoint, ( 1, 0)),
neighbourIfValid(cells, startingPoint, (-1, 0)),
neighbourIfValid(cells, startingPoint, ( 0, 1)),
neighbourIfValid(cells, startingPoint, ( 0, -1)))
.flatten
}
private def neighbourIfValid(cells: Array[Array[Cell]], origin: (Int, Int), delta: (Int, Int)) = {
val (x, y) = (origin._1 + delta._1, origin._2 + delta._2)
if (0 <= x && 0 <= y && x < cells.length && y < cells(0).length && cells(x)(y) == Free) {
Some(x, y)
} else None
}
def main (args: Array[String]): Unit = {
val (n, m) = (11, 5)
val cells: Array[Array[Cell]] = Array.fill(n, m)(Free)
cells(1)(1) = Blocked
cells(1)(2) = Blocked
cells(2)(1) = Blocked
val startingPoint = (5, 2)
println("Initial matrix:")
printMatrix(cells)((i, j, value) => if ((i, j) == startingPoint) "S" else if (value == Free) "." else "X")
val distancesMatrix = distances(cells, startingPoint)
println("\nDistances from starting point:")
printMatrix(distancesMatrix)((i, j, value) => if (value < 0) "X" else value.toString)
}
private def printMatrix[T](matrix: Array[Array[T]])(formatter: (Int, Int, T) => String) = {
for (i <- 0 until matrix.length) {
for (j <- 0 until matrix(0).length) {
print(formatter(i, j, matrix(i)(j)) + " ")
}
println()
}
}
}
I believe there is a DP (dynamic programming) solution to this problem, looking at this, code below. I realize this is for finding all possible paths to a cell but it can give insight on your condition about 'blanks' or 'walls'
#include <iostream>
using namespace std;
// Returns count of possible paths to reach cell at row number m and column
// number n from the topmost leftmost cell (cell at 1, 1)
int numberOfPaths(int m, int n)
{
// Create a 2D table to store results of subproblems
int count[m][n];
// Count of paths to reach any cell in first column is 1
for (int i = 0; i < m; i++)
count[i][0] = 1;
// Count of paths to reach any cell in first column is 1
for (int j = 0; j < n; j++)
count[0][j] = 1;
// Calculate count of paths for other cells in bottom-up manner using
// the recursive solution
for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
// By uncommenting the last part the code calculatest he total
// possible paths if the diagonal Movements are allowed
count[i][j] = count[i-1][j] + count[i][j-1]; //+ count[i-1][j-1];
}
return count[m-1][n-1];
}

How to fill a matrix with 0 and 1 recursively?

Ok so my problem is basically, I have a matrix for example
010
101
111
just random 1s and 0s. So I have arrays that are rowcount and colcount, which count the number of ones in each row and column. So rowcount for this is {1,2,3} and colcount is {2,2,2}. Now in another method, I am given the arrays rowcount and colcount, and in that method, I am supposed to create a matrix with the counts in rowcount and colcount, but the end matrix can be different. Than the original. I think I'm supposed to exhaust all permutations until a matrix works. The base case must stay the same.
Note: Math.random cannot be used.
private static void recur(int[][] m, int[] rowcount, int[] colcount, int r, int c)
//recursive helper method
{
if(compare(m, rowcount, colcount)) //base case: if new matrix works
{
System.out.println();
System.out.println("RECREATED");
display(m, rowcount, colcount); //we're done!
System.exit(0);
}
else
{
int[] temp_r = new int[m.length];
int[] temp_c = new int[m[0].length];
count(m, temp_r, temp_c);
if(rowcount[r] > temp_r[r] && colcount[c] > temp_c[c])
m[r][c] = 1;
if(r+1 < m.length)
recur(m,rowcount,colcount,r+1,c);
if(rowcount[r] < temp_r[r] || colcount[c] < temp_c[c])
m[r][c] = 0;
if(c+1 < m[0].length)
recur(m,rowcount,colcount,r,c+1);
}
}
private static boolean compare(int[][] m, int[] rowcount, int[] colcount)
{
int[] temp_r = new int[m.length];
int[] temp_c = new int[m[0].length];
count(m, temp_r, temp_c);
for (int x = 0; x < temp_r.length; x++)
{
if(temp_r[x] != rowcount[x])
return false;
}
for (int y = 0; y < temp_c.length; y++)
{
if(temp_c[y] != colcount[y])
return false;
}
return true;
}
public static void count(int[][] matrix, int[] rowcount, int[] colcount)
{
for(int x=0;x<matrix.length;x++)
for(int y=0;y<matrix[0].length;y++)
{
if(matrix[x][y]==1)
{
rowcount[x]++;
colcount[y]++;
}
}
}
Well, I decided I'd implement a solution, but instead of Java (which you haven't actually specified the solution needs to be in), I'm going to use Groovy (which is Java based anyway)! I've tried to use Java syntax where possible, it's not hard to extrapolate the Java code from this (but it is much more verbose!)
Note:
*Generating a random bit matrix, not using Math.random()
*I'm storing my matrix in a string i.e. [[0,1],[1,0]] = "0110"
*My solution relies heavily, on converting Integers to/from BinaryStrings (which is essentially what your matrix is!)
// Generate random matrix
int colSize = 3;
int rowSize = 4;
String matrix = '';
for (int i = 0; i < rowSize; i++){
String bits = Integer.toBinaryString(System.currentTimeMillis().toInteger());
matrix += bits.substring(bits.length() - colSize);
Thread.sleep((System.currentTimeMillis() % 1000) + 1);
}
def (cols1,rows1) = getCounts(matrix, colSize)
println "matrix=$matrix rows1=$rows1 cols1=$cols1"
// Find match (brute force!)
int matrixSize = colSize * rowSize
int start = 0
int end = Math.pow(Math.pow(2, colSize), rowSize) // 2 is number of variations, i.e. 0 and 1
for (int i = start; i <= end; i++){
String tmp = leftPad(Integer.toBinaryString(i), matrixSize, '0')
def (cols2,rows2) = getCounts(tmp, colSize)
if (cols1 == cols2 && rows1 == rows2){
println "Found match! matrix=$tmp"
break;
}
}
println "Finished."
String leftPad(String input, int totalWidth, String padchar){ String.format('%1$' + totalWidth + "s", input).replace(' ',padchar) }
int[][] getCounts(String matrix, int colSize){
int rowSize = matrix.length() / colSize
int[] cols = (1..colSize).collect{0}, rows = (1..rowSize).collect{0}
matrix.eachWithIndex {ch, index ->
def intval = Integer.parseInt(ch)
cols[index % colSize] += intval
rows[(int)index / colSize] += intval
}
[cols,rows]
}
Gives output:
matrix=001100011000 rows1=[1, 1, 2, 0] cols1=[1, 1, 2]
Found match! matrix=001001110000
Finished.
Brute force search logic:
Given a rowcount of [1,2,3]
And a colcount of [2,2,2]
Iterate over all matrix combinations (i.e. numbers 0 - 511 i.e. "000000000" -> "111111111")
Until the new matrix combination's rowcount and colcount matches the supplied rowcount and colcount
OK, your question and comments indicate you are on the right track. The code itself is a bit messy and it has obviously gone through some iterations. That's not great, but it's OK.
You are right, I believe, that you have to 'exhaust' the recursion until you find a new result that matches the existing column/row counts. So, attack the problem logically. First, create a method that can compare a matrix with a row/column count. You call it 'compare(...)'. I assume this method you have already works ;-). This is the method that marks the end of the recursion. When compare returns true, you should return up the recursion 'stack'. You should not do a System.exit(...).
So, the basic rule of recursion, you need an input, output, a method body that contains an exit-condition check, and a recursive call if the condition is not met....
Your problem has a specific issue which complicates things - you need to make copies if the input matrix every time you go down a recursion level. Alternatively you need to 'undo' any changes you make when you come up a level. The 'undo' method is faster (less memory copies).
So, the process is as follows, start with an all-zero matrix. Call your recursive function for the all-zero start point.
int[][] matrix = new int[width][height];
int rpos = 0;
boolean found = recur(matrix, rowcount, colcount, 0, 0);
This is how it will be called, and found will be true if we found a solution.
The difference here from your code is that recur now returns a boolean.
So, our recur method needs to do:
1. check the current matrix - return true if it matches.
2. make meaningful changes (within the limits that we've added)
3. recursively check the change (and add other changes).
Your method does not have an output, so there's no way to escape the recursion. So, add one (boolean in this case).
The way this can work is that we start in the top left, and try it with that bit set, and with it unset. For each contition (set or unset) we recursively test whether the next bit matches when set, or unset, and so on.... :
private static boolean recur(int[][] m, int[] rowcount, int[] colcount,
int row, int col) {
if (compare(m, rowcount, colcount)) {
// our matrix matches the condition
return true;
}
if (row >= m.length) {
return false;
}
int nextcol = col + 1;
int nextrow = row;
if (nextcol >= m[row].length) {
nextcol = 0;
nextrow++;
if (nextrow > m.length) {
return false;
}
}
// OK, so nextrow and nextcol are the following position, and are valid.
// let's set our current position, and tell the next level of recursion to
// start playing from the next spot along
m[row][col] = 1;
if (recur(m, rowcount, colcount, nextrow, nextcol)) {
return true;
}
// now unset it again
m[row][col] = 0;
if (recur(m, rowcount, colcount, nextrow, nextcol)) {
return true;
}
return false;
}
The above code is just hand-written, it may have bugs, etc. but try it. The lesson in here is that you need to test your consitions, and you need a strategy....

Recursive brute force maze solver Java

In an attempt to write a brute force maze solving C program, I've written this java program first to test an idea. I'm very new to C and intend to convert it after getting this right in java. As a result, I'm trying stick away from arraylists, fancy libraries, and such to make it easier to convert to C. The program needs to generate a single width path of shortest steps to solve a maze. I think my problem may be in fragmenting a path-storing array passed through each recursion. Thanks for looking at this. -Joe
maze:
1 3 3 3 3
3 3 3 3 3
3 0 0 0 3
3 0 3 3 3
0 3 3 3 2
Same maze solved by this program:
4 4 4 4 4
4 4 4 4 4
4 0 0 0 4
3 0 3 3 4
0 3 3 3 2
number notation are explained in code
public class javamaze {
static storage[] best_path;
static int best_count;
static storage[] path;
//the maze - 1 = start; 2 = finish; 3 = open path
static int maze[][] = {{1, 3, 3, 3, 3},
{3, 3, 3, 3, 3},
{0, 0, 0, 0, 3},
{0, 0, 3, 3, 3},
{3, 3, 3, 3, 2}};
public static void main(String[] args) {
int count1;
int count2;
//declares variables used in the solve method
best_count = 0;
storage[] path = new storage[10000];
best_path = new storage[10000];
int path_count = 0;
System.out.println("Here is the maze:");
for(count1 = 0; count1 < 5; count1++) {
for(count2 = 0; count2 < 5; count2++) {
System.out.print(maze[count1][count2] + " ");
}
System.out.println("");
}
//solves the maze
solve(findStart()/5, findStart()%5, path, path_count);
//assigns an int 4 path to the maze to visually represent the shortest path
for(int count = 0; count <= best_path.length - 1; count++)
if (best_path[count] != null)
maze[best_path[count].getx()][best_path[count].gety()] = 4;
System.out.print("Here is the solved maze\n");
//prints the solved maze
for(count1 = 0; count1 < 5; count1++) {
for(count2 = 0; count2 < 5; count2++){
System.out.print(maze[count1][count2] + " ");
}
System.out.print("\n");
}
}
//finds maze start marked by int 1 - this works perfectly and isn't related to the problem
public static int findStart() {
int count1, count2;
for(count1 = 0; count1 < 5; count1++) {
for(count2 = 0; count2 < 5; count2++) {
if (maze[count1][count2] == 1)
return (count1 * 5 + count2);
}
}
return -1;
}
//saves path coordinate values into a new array
public static void save_storage(storage[] old_storage) {
int count;
for(count = 0; count < old_storage.length; count++) {
best_path[count] = old_storage[count];
}
}
//solves the maze
public static Boolean solve(int x, int y, storage[] path, int path_count) {
//checks to see if grid squares are valid (3 = open path; 0 = wall
if (x < 0 || x > 4) { //array grid is a 5 by 5
//System.out.println("found row end returning false");
return false;
}
if (y < 0 || y > 4) {
//System.out.println("Found col end returning false");
return false;
}
//when finding finish - records the number of moves in static int best_count
if (maze[x][y] == 2) {
if (best_count == 0 || best_count > path_count) {
System.out.println("Found end with this many moves: " + path_count);
best_count = path_count;
save_storage(path); //copies path counting array into a new static array
}
}
//returns false if it hits a wall
if (maze[x][y] == 0)
return false;
//checks with previously crossed paths to prevent an unnecessary repeat in steps
for(storage i: path)
if (i != null)
if (i.getx() == x && i.gety() == y)
return false;
//saves current recursive x, y (row, col) coordinates into a storage object which is then added to an array.
//this array is supposed to fragment per each recursion which doesn't seem to - this may be the issue
storage storespoints = new storage(x, y);
path[path_count] = storespoints;
//recurses up, down, right, left
if (solve((x-1), y, path, path_count++) == true || solve((x+1), y, path, path_count++) == true ||
solve(x, (y+1), path, path_count++) == true || solve(x, (y-1), path, path_count++) == true) {
return true;
}
return false;
}
}
//stores (x, y) aka row, col coordinate points
class storage {
private int x;
private int y;
public storage(int x, int y) {
this.x = x;
this.y = y;
}
public int getx() {
return x;
}
public int gety() {
return y;
}
public String toString() {
return ("storage coordinate: " + x + ", " + y + "-------");
}
}
This wasn't originally intended to be an answer but it sort of evolved into one. Honestly, I think starting in Java and moving to C is a bad idea because the two languages are really nothing alike, and you won't be doing yourself any favors because you will run into serious issues porting it if you rely on any features java has that C doesn't (i.e. most of them)
That said, I'll sketch out some algorithmic C stuff.
Support Structures
typedef
struct Node
{
int x, y;
// x and y are array indices
}
Node;
typedef
struct Path
{
int maxlen, head;
Node * path;
// maxlen is size of path, head is the index of the current node
// path is the pointer to the node array
}
Path;
int node_compare(Node * n1, Node * n2); // returns true if nodes are equal, else false
void path_setup(Path * p, Node * n); // allocates Path.path and sets first node
void path_embiggen(Path * p); // use realloc to make path bigger in case it fills up
int path_toosmall(Path * p); // returns true if the path needs to be reallocated to add more nodes
Node * path_head(Path * p); // returns the head node of the path
void path_push(Path * p, Node * n); // pushes a new head node onto the path
void path_pop(Path * p); // pops a node from path
You might to change your maze format into an adjacency list sort of thing. You could store each node as a mask detailing which nodes you can travel to from the node.
Maze Format
const int // these constants indicate which directions of travel are possible from a node
N = (1 << 0), // travel NORTH from node is possible
S = (1 << 1), // travel SOUTH from node is possible
E = (1 << 2), // travel EAST from node is possible
W = (1 << 3), // travel WEST from node is possible
NUM_DIRECTIONS = 4; // number of directions (might not be 4. no reason it has to be)
const int
START = (1 << 4), // starting node
FINISH = (1 << 5); // finishing node
const int
MAZE_X = 4, // maze dimensions
MAZE_Y = 4;
int maze[MAZE_X][MAZE_Y] =
{
{E, S|E|W, S|E|W, S|W },
{S|FINISH, N|S, N|START, N|S },
{N|S, N|E, S|E|W, N|S|W },
{N|E, E|W, N|W, N }
};
Node start = {1, 2}; // position of start node
Node finish = {1, 0}; // position of end node
My maze is different from yours: the two formats don't quite map to each other 1:1. For example, your format allows finer movement, but mine allows one-way paths.
Note that your format explicitly positions walls. With my format, walls are conceptually located anywhere where a path is not possible. The maze I created has 3 horizontal walls and 5 vertical ones (and is also enclosed, i.e. there is a continuous wall surrounding the whole maze)
For your brute force traversal, I would use a depth first search. You can map flags to directions in a number of ways, like maybe the following. Since you are looping over each one anyway, access times are irrelevant so an array and not some sort of faster associative container will be sufficient.
Data Format to Offset Mappings
// map directions to array offsets
// format is [flag], [x offset], [y offset]
int mappings[][] =
{
{N, -1, 0},
{S, 1, 0},
{E, 0, 1},
{W, 0, -1}
}
Finally, your search. You could implement it iteratively or recursively. My example uses recursion.
Search Algorithm Pseudocode
int search_for_path(int ** maze, char ** visited, Path * path)
{
Node * head = path_head(path);
Node temp;
int i;
if (node_compare(head, &finish)) return 1; // found finish
if (visited[head->x][head->y]) return 0; // don't traverse again, that's pointless
visited[head->x][head->y] = 1;
if (path_toosmall(path)) path_embiggen(path);
for (i = 0; i < NUM_DIRECTIONS; ++i)
{
if (maze[head->x][head->y] & mappings[i][0]) // path in this direction
{
temp = {head->x + mappings[i][1], head->y + mappings[i][2]};
path_push(path, &temp);
if (search_for_path(maze, visited, path)) return 1; // something found end
path_pop(path);
}
}
return 0; // unable to find path from any unvisited neighbor
}
To call this function, you should set everything up like this:
Calling The Solver
// we already have the maze
// int maze[MAZE_X][MAZE_Y] = {...};
// make a visited list, set to all 0 (unvisited)
int visited[MAZE_X][MAZE_Y] =
{
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0}
};
// setup the path
Path p;
path_setup(&p, &start);
if (search_for_path(maze, visited, &path))
{
// succeeded, path contains the list of nodes containing coordinates from start to end
}
else
{
// maze was impossible
}
It's worth noting that because I wrote this all in the edit box, I haven't tested any of it. It probably won't work on the first try and might take a little fiddling. For example, unless start and finish are declared globally, there will be a few issues. It would be better to pass the target node to the search function instead of using a global variable.

Categories

Resources