changing 2-d maze solver to be used with 1-d - java

Given code that included everything to build a maze, I was to write the makeMove method to solve the maze, which I have completed and is working fine. However everything is done to use 2-D array with the maze and visited, I need to edit this to be used with 1-d array for maze and visited.
public abstract class AbstractMaze {
protected int startRow; // starting row
protected int startCol; // starting column
protected int endRow; // ending row
protected int endCol; // ending column
/**
* Declare the maze, 1's are walls and 0's are open
*/
protected int[][] maze;
protected AbstractMaze(int[][] maze, int startRow, int startCol, int endRow, int endCol) {
super();
this.maze = maze;
this.startRow = startRow;
this.startCol = startCol;
this.endRow = endRow;
this.endCol = endCol;
}
public void solve() {
makeMove( startRow, startCol )
}
protected abstract void makeMove( int row, int col );
}
public class Maze2 extends AbstractMaze
{
public Maze2(int[][] maze, int startRow, int startCol, int endRow, int endCol) {
super(maze, startRow, startCol, endRow, endCol);
}
int MAX_ROWS = endRow + 1;
int MAX_COLS = endCol + 1;
boolean[][]visited = new boolean[MAX_ROWS][MAX_COLS];
protected void makeMove( int row, int col )
{
boolean found = false;
if (row < 0 || row >= MAX_ROWS || col < 0 || col >= MAX_COLS || visited[row][col] || maze[row][col] == 1)
return;
visited[row][col] = true;
found = row == endRow && col == endCol;
if (!found) {
makeMove(row, col - 1);
makeMove(row, col + 1);
makeMove(row - 1, col);
makeMove(row + 1, col);
}
Do I need to change every place where maze[][] is and visited[][]? What is the simplest way to go about this?
Thanks for any and all help!

I assume that you want to change the given 2D maze array into a 1D maze class member. Declare the maze member as
int ROWS = maze.length;
int COLS = maze[0].length;
this.maze = new int[ROWS * COLS];
You can index this array as maze[COLS * row + col]. You'll then need to copy the elements over:
for (int r = 0; r < ROWS; r++)
for (int c = 0; c < COLS; c++)
this.maze[COLS * r + c] = maze[r][c];
As you can see, accessing an element is accomplished via this.maze[COLS * r + c] instead of this.maze[r][c]. You can think of it as taking the 2D array and joining the rows together to form a long 1D array.
Similarly, the visited array can be declared as visited[MAX_COLS * MAX_ROWS] and indexed via visited[MAX_COLS * row + col].

Related

How to sum rows of a 2D array individually with Java?

i have a matrix and I want to sum all content on the array from one point to another of the matrix, so in other words it might be that in row 1 i want to start to sum from col2 then sume row1 and row2 completely and then on row3 only until the position on number2
so leet me give you an example
class Lab {
public static void main(string[] args) {
int [][] scores = {{ 2, 8, 3, 2, 6 },
{ 3, 2, 8, 1, 0 },
{ 6, 9, 6, 3, 4 },
{ 5, 4, 2, 4, 5 }};
outputArray(scores);
}
public int sumRow(int[][] matrix, int row)
{
int sum = 0;
startrow = scores[1][]
lastrow =scores[3][]
startcol =scores[][2]
lastcol = scores[][2]
for(int i = startrow; i==lastrow;i++){
for (int j=startcol ; j==lastcol;j++) {
sum += scores[i][j];
return sum;
}
basically the sum of
row 1 -> 8, 1, 0
row 2 -> 6, 9, 6, 3, 4
row 3 -> 5, 4, 2
but done in one for loop (or any other method you think will be best to do so)
not sure if it can be done at once or if its needed to go row by row and then sum all the rows?
thanks!
The sales by month, in my opinion, greatly clarifies what you want to do.
To accomplish that, the sum method should have parameters to specify the row and column of the first cell, and row and column of the last cell to be summed.
You might try something like this:
public static int sumRange ( int matrix[][]
, int startRow, int startCol
, int endRow , int endCol ) {
int sum = 0;
int colIdx, rowIdx;
// add elements at end of first row
for (colIdx = startCol; colIdx < matrix [0].length; colIdx++) {
sum += matrix [startRow][colIdx];
}
// add elements of "in-between" rows, if any
for (rowIdx = startRow + 1; rowIdx < endRow; rowIdx++) {
for (colIdx = 0; colIdx < matrix [rowIdx].length; colIdx++) {
sum += matrix [rowIdx][colIdx];
}
}
// add elements at start of last row
for (colIdx = 0; colIdx <= endCol; colIdx++) {
sum += matrix [endRow][colIdx];
}
return sum;
}
The above uses 4 for loops, but is straightforward -- almost.
You could do it with a pair of nested for loops, but with an if that has several tests.
public static int sumRange ( int matrix[][]
, int startRow, int startCol
, int endRow , int endCol ) {
int sum = 0;
for (int rowIdx = startRow; rowIdx <= endRow; rowIdx++) {
for (int colIdx = 0; colIdx < matrix[rowIdx].length;colIdx++) {
if ( rowIdx == startRow && colIdx >= startCol
|| rowIdx == endRow && colIdx <= endCol
|| rowIdx > startRow && rowIdx < endRow ) {
sum += matrix [rowIdx][colIdx];
}
}
}
return sum;
}
Is it possible to do it with one for loop? It is.
public static int sumRange ( int matrix[][]
, int startRow, int startCol
, int endRow , int endCol ) {
int sum = 0;
int len = matrix[0].length;
for ( int idx = len * startRow + startCol ;
idx <= len * endRow + endCol ;
idx++ ) {
sum += matrix [idx / len] [idx % len];
}
return sum;
}
There are preconditons:
All rows in matrix have the same length.
The values for startRow, endRow, startCol, endCol are valid when used as row and column indices for the matrix parameter.
In the first two examples, startRow < endRow.
In the third example, startRow <= endRow . If startRow == endRow, then startCol < endCol.
Note the 2nd precondition implies the first two examples won't work when startRow == endRow. To fix the bug, precede the first for loop with an if statement to check for that, a for loop to sum the proper columns, and a return statement.
Because, in your example, the matrix was included as a parameter, and there was no use of instance variables, I made the methods static in these examples. If the matrix the method is supposed to use is an instance variable, remove int matrix [][] from the parameter list, and remove static from the method header.

Building Tic-Tac-Toe Board and am stuck on an infinite loop. Any Suggestions?

I am trying to make the board display alternating X's and O's on each square of the board and am having trouble not being able to stop the program from infinitely printing on the first space and switching markers. First I will show the class:
public class Board {
int cellsize = 4;
int cellsperrow = 3;
int rowsize = cellsize * cellsperrow;
public final char[] marker = new char [] {'X'};
public String boardRep = "___|___|___\n___|___|___\n | | ";
public final char [] [] board = new char[cellsperrow][cellsperrow];
public Board(){
for(int R = 0; R < board.length; ++R){
for(int C = 0; C < board[R].length; ++C){
board[R][C] = ' ';
}
}
}
boolean IsEmpty(int row, int col){
return board[row][col] == ' ';
}
public boolean markBoard(char marker, int row, int col){
if(!IsEmpty(row,col) || !isInRangeIndex(row,col)) {
boardRep = boardRep.substring(0, row*rowsize) + boardRep.substring(row*rowsize,(row*rowsize) + (col*cellsize) + 1) + marker + boardRep.substring((row*rowsize) + (col*cellsize) + 2, boardRep.length());
return false;
}
board[row][col] = marker;
return true;
}
boolean isInRange(int V){
return V >= 0 && V <= 2;
}
boolean isInRangeIndex(int r, int c){
return isInRange(r) && isInRange(c);
}
}
This is the Main:
Board B = new Board();
char [] markers = {'X','O'};
int marker = 0;
int numRows = 3;
int numCols = 3;
for(int row = 0; row < numRows; ++row){
for(int col = 0; col < numCols; ++col){
while(true){
System.out.println(B.boardRep);
B.markBoard(markers[marker],row,col);
marker = (marker + 1) %markers.length;
System.out.println(B.boardRep);
}
}
}
}
}
Any suggestions are appreciated. Thank you! I apologize if this is not formatted right I am newer to this and have never used this website before.

Common DFS question "Connect cell" or "find island" but only find rectangular shape

I've just learned an algorithm called DFS and when I watched the videos, the most popular practice or example to use DFS is the Connected Cells or find islands one which is a 2D array with 0 and 1. But I really wish to know if I want the island shape only to be rectangular(or square), what should I do or how can I change the if or for loop in the program. Here's the code I'm looking at:
// No. of rows and columns
static final int ROW = 3, COL = 5;
// A function to check if a given cell (row, col) can
// be included in DFS
boolean isSafe(int M[][], int row, int col,
boolean visited[][])
{
// row number is in range, column number is in range
// and value is 1 and not yet visited
return (row >= 0) && (row < ROW) && (col >= 0) && (col < COL) && (M[row][col] == 1 && !visited[row][col]);
}
// A utility function to do DFS for a 2D boolean matrix.
// It only considers the 8 neighbors as adjacent vertices
void DFS(int M[][], int row, int col, boolean visited[][])
{
// These arrays are used to get row and column numbers
// of 8 neighbors of a given cell
int rowNbr[] = new int[] { -1, -1, -1, 0, 0, 1, 1, 1 };
int colNbr[] = new int[] { -1, 0, 1, -1, 1, -1, 0, 1 };
// Mark this cell as visited
visited[row][col] = true;
// Recur for all connected neighbours
for (int k = 0; k < 8; ++k)
if (isSafe(M, row + rowNbr[k], col + colNbr[k], visited))
DFS(M, row + rowNbr[k], col + colNbr[k], visited);
}
// The main function that returns count of islands in a given
// boolean 2D matrix
int countIslands(int M[][])
{
boolean visited[][] = new boolean[ROW][COL];
int count = 0;
for (int i = 0; i < ROW; ++i)
for (int j = 0; j < COL; ++j)
if (M[i][j] >= 100 && !visited[i][j])
{
DFS(M, i, j, visited);
++count;
}
return count;
}

Use a depth first to traverse a matrix

Problem
You are given a two-dimensional array (matrix) of potentially unequal height and width containing only 0s and 1s. Each 0 represents land, and each 1 represents part of a river. A river consists of any number of 1s that are either horizontally or vertically adjacent (but not diagonally adjacent). The number of adjacent 1s forming a river determine its size. Write a function that returns an array of the sizes of all rivers represented in the input matrix. Note that these sizes do not need to be in any particular order.
Input
[
[1,0,0,1,0],
[1,0,1,0,0],
[0,0,1,0,1],
[1,0,1,0,1],
[1,0,1,1,0],
]
Output [1,2,2,2,5]
My Approach
After evaluating the problem i felt like this should be done using a graph traversal like algorithm maybe depth first search. So that is exactly what i do .
I traverse the matrix from top left and see if the value is visited and if it is not then and if the value is 1 then i traverse all it's nodes and keep a counter to keep size of the river. In the end i update an array list with the total river size.
For some reason my result is not correct and i am not sure what i did wrong. I hand traced my code too but can't figure out the issue.
My Code
import java.util.ArrayList;
class Program {
public static ArrayList<Integer> riverSizes(int[][] matrix) {
ArrayList<Integer> result = new ArrayList<Integer>();
boolean [][] visitStatus = new boolean [matrix.length][matrix[0].length];
for(int row = 0; row<matrix.length; row++){
for(int col = 0; col<matrix.length; col++){
int count = 0;
count = traverseMatrix(row,col,matrix,visitStatus,count);
result.add(count);
}
}
return result;
}
public static int traverseMatrix(int row, int col, int [][] matrix, boolean [][] visitStatus, int count){
if(visitStatus[row][col] == true){
return count;
}else if(matrix[row][col] == 0){
visitStatus[row][col] = true;
return count;
}else{
count++;
visitStatus[row][col] = true;
if(isValid(row,col-1,matrix)){
return traverseMatrix(row,col-1,matrix,visitStatus,count);
}
if(isValid(row,col+1,matrix)){
return traverseMatrix(row,col+1,matrix,visitStatus,count);
}
if(isValid(row-1,col,matrix)){
return traverseMatrix(row-1,col,matrix,visitStatus,count);
}
if(isValid(row+1,col,matrix)){
return traverseMatrix(row+1,col,matrix,visitStatus,count);
}
}
return count;
}
public static boolean isValid(int row, int col,int[][] matrix){
return (row >= 0 && row < matrix.length) && (col >= 0 && col < matrix[0].length);
}
}
you are given a two-dimensional array (matrix) of potentially unequal height and width 
But you are doing the operation for always same size of matrix both in height and width
for(int row = 0; row<matrix.length; row++){
for(int col = 0; col<matrix.length; col++){ .. }}
you should use the dimension like following way, rest of the things are enough well I guess
..
for(int row = 0; row<matrix.length; row++){
for(int col = 0; col<matrix[row].length; col++){ .. }}
and the changes need to apply in function 'isValid' also
public static boolean isValid(int row, int col,int[][] matrix){
return (row >= 0 && row < matrix.length) && (col >= 0 && col < matrix[row].length);
}
Convert count to a local variable and accumulate it:
static int traverseMatrix(int row, int col, int[][] matrix, boolean[][] visitStatus) {
if (visitStatus[row][col] || matrix[row][col] == 0) {
return 0;
}
visitStatus[row][col] = true;
int count = 1;
if (isValid(row, col - 1, matrix)) {
count += traverseMatrix(row, col - 1, matrix, visitStatus);
}
...
return count;
}
In addition to #OleksandrPyrohov's answer, also check if the current cell is visited already before calling traverseMatrix :
public static ArrayList<Integer> riverSizes(int[][] matrix) {
ArrayList<Integer> result = new ArrayList<Integer>();
boolean [][] visitStatus = new boolean [matrix.length][matrix[0].length];
for(int row = 0; row<matrix.length; row++){
for(int col = 0; col<matrix.length; col++){
if ( !visitStatus[row][col] ) {
int count = 0;
count = traverseMatrix(row,col,matrix,visitStatus,count);
result.add(count);
}
}
}
return result;
}
My solution is written in C#, but it's similar to Java:
You can replace List with ArrayList
Code:
public static List<int> RiverSizes(int[,] matrix)
{
var sizes = new List<int>();
bool[,] visited = new bool[matrix.GetLength(0), matrix.GetLength(1)];
for (int row = 0; row < matrix.GetLength(0); row++)
for (int col = 0; col < matrix.GetLength(1); col++)
if (visited[row, col])
continue;
else
Traverse(matrix, row, col, visited, sizes);
return sizes;
}
public static void Traverse(int[,] matrix, int row, int col, bool[,] visited, List<int> sizes)
{
int currentSize = 0;
var toExplore = new List<int[]>
{
new int[] { row, col }
};
while (toExplore.Count > 0)
{
var current = toExplore[^1];
toExplore.RemoveAt(toExplore.Count - 1);
row = current[0];
col = current[1];
if (visited[row, col])
continue;
visited[row, col] = true;
if (matrix[row, col] == 0)
continue;
currentSize++;
foreach (int[] item in GetNeighbours(matrix, row, col, visited))
toExplore.Add(item);
}
if (currentSize > 0)
sizes.Add(currentSize);
}
public static List<int[]> GetNeighbours(int[,] matrix, int row, int col, bool[,] visited)
{
List<int[]> neighbours = new List<int[]>();
if (row > 0 && !visited[row - 1, col])
neighbours.Add(new int[] { row - 1, col });
if (row < matrix.GetLength(0) - 1 && !visited[row + 1, col])
neighbours.Add(new int[] { row + 1, col });
if (col > 0 && !visited[row, col - 1])
neighbours.Add(new int[] { row, col - 1 });
if (col < matrix.GetLength(1) - 1 && !visited[row, col + 1])
neighbours.Add(new int[] { row, col + 1 });
return neighbours;
}
I hope it helps ^-^

Game of life - edges do not change

I saw Conway's Game of Life and wanted to make my own. However the cells at the edges somehow don't follow the rules and just stay alive (or dead) the whole time. Does anybody know where I made the mistake?
This is my code: (I only uploaded the class where I applied the rules. If the other classes are needed to solve the problem, I can upload them as well)
import java.util.Arrays;
/**
* The class Grid does the initialization of the game of life and the application of the rules.
* It is a 2D array of the type Cell. It saves the cells and uses a copy of it to apply the rules.
*
*/
public class Grid
{
public int col;
public int row;
public int x,y;
public Cell [][] array; //2D array of the type Cell
public Cell [][] arraycopy;
/**
* This constructor is to create the initial generation of cells and set the state of random 20% to true (=alive).
* #param col the number of columns
* #param row the number of rows
*
*/
public Grid(int col, int row)
{
this.col = col;
this.row = row;
this.array = new Cell [col][row];
//Loops through every spot in the 2D array
for (int x = 0; x < col; x++)
{
for (int y=0; y < row; y++)
{
//set randomly 20% of the cells' state to "true"
if (Math.random() <= 0.2)
{
Cell cell = new Cell (true);
this.array[x][y]= cell;
}
else
{
Cell cell = new Cell (false);
this.array[x][y]= cell;
}
}
}
}
/**
* This method will count the alive cells in a 3*3 neighboorhood and apply the rules of life.
* This method uses arraycopy.
*
*/
public void lifeSteps()
{
//Works with a copy of the array and the cells
this.arraycopy = new Cell [col][row];
for (int x = 0; x < col; x++)
{
for (int y=0; y < row; y++)
{
this.arraycopy [x][y] = new Cell(this.array[x][y].getState());
}
}
//Looping through the cells, but the cells at the edge are skipped
for (int x = 1; x < col-1; x++)
{
for (int y= 1; y < row-1; y++)
{
//Looping through all the neighbors
int numNeighborsAlive = 0;
for (int i = x-1; i <= x+1; i++)
{
for (int j = y-1; j <= y+1; j++)
{
//In a 3x3 neighborhood the middle cell needs to be skipped
if ((x != i) && (y != j))
{
//Only the cells that are alive (true) are added
if (arraycopy [i][j].getState() == true)
{
numNeighborsAlive += 1;
}
}
}
}
//Apply the rules of life
if ((array [x][y].getState()) && (numNeighborsAlive < 2 || numNeighborsAlive >3)) //Loneliness and Overpopulation
{
array[x][y].setState(false);
}
else if ((array [x][y].getState() == false) && (numNeighborsAlive ==3)) //Birth
{
array[x][y].setState(true);
}
else
{ //stasis
}
}
}
}
/**
* This method will return the statement for the array.
* #return the 2D array of the type Cell
*/
public Cell[][] returnGrid ()
{
return this.array;
}
/**
* This method will test if everything is working well by printing zeros and ones.
*
*/
public void printTest()
{
System.out.println("\t"); // a new line
for (int x = 0; x < col; x++)
{
for (int y=0; y < row; y++)
{
// assigns 1 if the cell is alive and 0 if it is dead
if (array[x][y].getState() == true)
{
System.out.print("1");
}
else
{
System.out.print("0");
}
}
System.out.println(""); // will be displayed as colums and rows
}
System.out.println("\t"); // a new line
}
}
The borders are not processed, so there are always 8 neighbors.
One can handle all array positions, and determine the neighbors. These could be hardwired in the cell at initialisation, or - as below - determined dynamically.
For that I use an offset vector with a delta x and delta y in -1, 0, 1.
private static final int[][] MIDDLE_NEIGHBORS =
{
{-1, -1}, {-1, 0}, {-1, 1},
{0, -1}, {0, 1},
{1, -1}, {1, 0}, {1, 1}
};
private static final int[][] LEFT_TOP_NEIGHBORS =
{
{0, 1},
{1, 0}, {1, 1}
};
...
int[][] neighborDeltaXY(int x, int y, int col, int row) {
if (1 < x && x < col-1 && 1 < y && y < row-1) {
return MIDDLE_NEIGHBORS;
}
if (x == 0 && row == 0) {
return LEFT_TOP_NEIGHBORS;
}
...
}
Or you might be more comfortable with nested conditions:
int[][] neighborDeltaXY(int x, int y, int col, int row) {
if (x == 0) {
if (y == 0) {
return LEFT_TOP_NEIGHBORS;
} else if (y == row - 1) {
return ...;
} else {
return ...;
}
} else if (x == col - 1) {
if (y == 0) {
return ...;
} else if (y == row - 1) {
return ...;
} else {
return ...;
}
} else {
if (y == 0) {
return ...;
} else if (y == row - 1) {
return ...;
} else {
return MIDDLE_NEIGHBORS;
}
}
}
Useful is to have a method doing the actual counting on the board:
int countNeighborsAlive(Cell[][] old, int x, int y, int col, int row) {
int numNeighborsAlive = 0;
int[][] neighbors = neighborDeltaXY(x, y, col, row);
for (int[] neighbor : neighbors) {
int xn = x + neighbor[0];
int yn = y + neighbor[1];
if (old[xn][yn].getState()) {
++numNeighborsAlive;
}
}
return numNeighborsAlive;
}
So the time loop becomes simpler:
for (int x = 0; x < col; x++) {
for (int y= 0; y < row; y++) {
int numNeighborsAlive = countNeighborAlive(arraycopy, x, y, col, row);
... numNeighborsAlive
In the game of life one could make different geometries, having above y == 0 the y == row - 1, so the world wraps around the borders.
Also feasible is to take the original board and place it in a larger grid, so the visible cells are in [1, col - 1), [1, row - 1). The invisible borders then always remain 0. Not so nice for the game of life, but other grid based games are so walled in.
Instead Do Or
x += 1; ++x; x++
if (c == true) if (c)
if (d == false) if (!d)

Categories