Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions src/main/java/algorithms/curated170/medium/maze2/TheMazeIIBFS.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package algorithms.curated170.medium.maze2;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;


public class TheMazeIIBFS {
int[][] maze;

public int shortestDistance(int[][] maze, int[] start, int[] dest) {
this.maze = maze;

int[][] distance = new int[maze.length][maze[0].length];
for (int[] row: distance)
Arrays.fill(row, Integer.MAX_VALUE);

distance[start[0]][start[1]] = 0;

int[][] directions = {{0, -1}, {1, 0}, {-1, 0}, {0, 1}};

Queue <int[]> queue = new LinkedList<>();
queue.add(start);
while (!queue.isEmpty()) {

int[] s = queue.remove();

for (int[] dir: directions) {
int x = s[0] + dir[0];
int y = s[1] + dir[1];
int count = 0;
while (canPass(x, y)) {
x += dir[0];
y += dir[1];
count++;
}

int prx = x - dir[0];
int pry = y - dir[1];

int total = distance[s[0]][s[1]] + count;

if ( total < distance[prx][pry]) {
distance[prx][pry] = total;
queue.add(new int[] {prx, pry});
}
}
}
return distance[dest[0]][dest[1]] == Integer.MAX_VALUE ? -1 : distance[dest[0]][dest[1]];
}

boolean canPass(int nextX, int nextY) {
return (nextX >= 0 && nextY >= 0
&& nextX < maze.length
&& nextY < maze[0].length
&& maze[nextX][nextY] == 0);

}
}
85 changes: 85 additions & 0 deletions src/main/java/algorithms/curated170/medium/maze2/TheMazeIIDFS.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package algorithms.curated170.medium.maze2;

import java.util.Arrays;


public class TheMazeIIDFS {


int[][] maze;
int[] destination;
int[][] distance;

int[][] directions = {{0, -1}, {1, 0}, {-1, 0}, {0, 1}};

public int shortestDistance(int[][] maze, int[] start, int[] dest) {

this.maze = maze;
this.destination = dest;
this.distance = new int[maze.length][maze[0].length];

for (int[] row: distance)
Arrays.fill(row, Integer.MAX_VALUE);

distance[start[0]][start[1]] = 0;

dfs(start[0], start[1], -1);

return distance[dest[0]][dest[1]] == Integer.MAX_VALUE ? -1 : distance[dest[0]][dest[1]];
}

public void dfs(int x, int y, int arrivedFrom) {


if (x == destination[0] && y == destination[1]) {
return;
}


for (int i = 0; i<4; i++){

if((i == 0 && arrivedFrom == 3)
|| (i == 1 && arrivedFrom == 2)
|| (i == 2 && arrivedFrom == 1)
|| (i == 3 && arrivedFrom == 0))
{
continue;
}

int dirx = directions[i][0];
int diry = directions[i][1];

int nextX = x + dirx;
int nextY = y + diry;

int count = 0;

while (canPass(nextX, nextY) ) {

nextX += dirx;
nextY += diry;
count++;
}

int prx = nextX - dirx;
int pry = nextY - diry;

int total = distance[x][y] + count;

if (total < distance[prx][pry]) {

distance[prx][pry] = total;
dfs(prx, pry, i);
}

}
}
boolean canPass(int nextX, int nextY) {
return (nextX >= 0 && nextY >= 0
&& nextX < maze.length
&& nextY < maze[0].length
&& maze[nextX][nextY] == 0);

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package algorithms.curated170.medium.maze2;

import java.util.Arrays;
import java.util.PriorityQueue;


public class TheMazeIIDijkstra {
final static int VISITED = -1;
int[][] maze;
public int shortestDistance(int[][] maze, int[] start, int[] dest) {

this.maze = maze;

return dijkstra(start, dest);
}

public int dijkstra( int[] start, int[] destination) {

PriorityQueue<int[]> pq = new PriorityQueue<>((p1, p2) -> p1[2] - p2[2]);
int[][] directions = {{0, -1}, {1, 0}, {-1, 0}, {0, 1}};

pq.add(new int[]{start[0], start[1], 0});
while (!pq.isEmpty()) {

int[] startPoint = pq.poll();

int x = startPoint[0];
int y = startPoint[1];

if(maze[x][y]==-1) continue;

maze[x][y] = VISITED;
if (x == destination[0] && y == destination[1]) {
return startPoint[2];
}


for (int[] dir: directions) {
int dirx = dir[0];
int diry = dir[1];

int nextX = x;
int nextY = y;

int currentDistance = startPoint[2];

while (canPass(nextX, nextY)) {
nextX += dirx;
nextY += diry;
currentDistance++;
}

nextX -= dirx;
nextY -= diry;
currentDistance--;


if(maze[nextX][nextY]!=-1) {

pq.add(new int[]{nextX, nextY, currentDistance});
}
}
}
return VISITED;
}

boolean canPass(int nextX, int nextY) {
return (nextX >= 0 && nextY >= 0
&& nextX < maze.length
&& nextY < maze[0].length
&& maze[nextX][nextY] != 1);
Copy link
Collaborator

@ErdemT09 ErdemT09 May 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we check for this condition unlike in the previous two solutions?
maze[nextX][nextY] == 0

Copy link
Collaborator

@ErdemT09 ErdemT09 May 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have understood the reason why we don't do this.
In the previous solution, the tiles that we come across are either empty or a wall. If empty, we move through them. If wall, we stop. Here, we have a three valued logic: A tile is either empty but visited, empty or a wall. We should be able to move through an empty tile even if it is visited. At the end, we can't stop and branch off there, but whilst moving to another valid tile, we should be able to pass them.

After all, we start the canPass loop from an already visited tile. This means we have to consider -1 as a valid passable tile value.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation Erdem. Appreciated.


}
}