I'm having difficulty trying to turn a algorithm that was hinted to us into usable code. We are given a Direction enum that has the 8 coordinates (N, NE, NW, S, SE. SW. E, W) along with the exit HERE.
This is the hinted algorithm:
getPathToExit(row, col):
if (row, col) is outside of the map:
return an empty list
else if (row, col) is an obstacle:
return an empty list
else if (row, col) is marked as visited or as deadend:
return an emtpy list
else if (row, col) is the exit:
//optional: mark exit as visited
return a list containing Direction.HERE
else:
//try to find a path from current square to exit:
mark current square as visited (that is, part of path)
for each neighbor of current square:
path = path from neighbor to exit
if path is not empty:
add (direction to neighbor) to start of path
return path
//after for loop: no path exists from this square to exit
mark current square as deadend
return empty list
This is the code I have been working on for a while:
public java.util.ArrayList<Direction> getPathToExit(){
for (int x=0; x<map.length; x++){
for (int y=0; y<map[x].length; y++){
if (map[x][y]=='S'){
this.startRow=x;
this.startCol=y;
}
}
}
System.out.println("start "+startRow+", "+startCol);
return getPathToExit(this.startRow, this.startCol);
}
private java.util.ArrayList<Direction> getPathToExit(int row, int col){
Direction [] dirs = Direction.values();
ArrayList<Direction> path = new ArrayList<Direction>();
getPathToExit(row, col);
if (row < 0 || col < 0 || row > map.length || col > map[row].length){
return null;
}
else if (map[row][col] != ' '){
return null;
}
else if (map[row][col] == 'E'){
path.add(Direction.HERE);
return path;
}
else {
for (int x=0; x<dirs.length-1; x++){
int nextRow = row + dirs[x].getRowModifier();
int nextCol = col + dirs[x].getColModifier();
path = getPathToExit(nextRow, nextCol);
}
}
return path;
}
This is the enum class:
public enum Direction {
N, NE, E, SE, S, SW, W, NW, HERE;
/**
* Returns the X/column change on the screen that is associated with
* this direction: -1 for W, 0 for N/S, and +1 for E.
*/
public int getColModifier() {
int mod;
switch (this) {
case NW:
case W:
case SW:
mod = -1;
break;
case NE:
case E:
case SE:
mod = +1;
break;
default:
mod = 0;
break;
}
return mod;
}
/**
* Returns the Y/row change on the screen that is associated with
* this direction: -1 for N, 0 for E/W, and +1 for south.
*/
public int getRowModifier() {
int mod;
switch (this) {
case N:
case NE:
case NW:
mod = -1;
break;
case S:
case SE:
case SW:
mod = +1;
break;
default:
mod = 0;
break;
}
return mod;
}
/** As {#link #getColModifier()} */
public int getXModifier() {
return this.getColModifier();
}
/** As {#link #getRowModifier()} */
public int getYModifier() {
return this.getRowModifier();
}
/**
* Returns the direction that is the opposite of this one.
* For example, <code>Direction.NE.reverse() == Direction.SW</code>.
* (The opposite of HERE is still HERE though.)
*/
public Direction reverse() {
if (this == HERE) {
return this;
}else {
int reversed = (this.ordinal() + 4) % 8;
Direction[] dirs = Direction.values();
return dirs[reversed];
}
}
}
Thanks in advance.
There are two issues in the code:
(1)
In the main for loop:
for (int x=0; x<dirs.length-1; x++){
int nextRow = row + dirs[x].getRowModifier();
int nextCol = col + dirs[x].getColModifier();
path = getPathToExit(nextRow, nextCol);
}
You need to check if the recursive call: getPathToExit() returned a not null list. If it had, you should break the loop and push the relevant direction to its start. You already found a path - not point to keep on checking the rest!
(2) In order for your algorithm to be complete (find a solution if one exists), you need to maintain a visited set, and avoid revisiting already visited nodes.
Have a look at the following example:
-------
|S |x1|
-------
|x2|E |
-------
where all are valid squares (no obstacles), S is the start and E is the end.
Now, assume the order of directions is right,left, ....
The code (without visited set) will do the following:
go right (to x1).
go right - out of maze, go back.
go left (to S).
go right (to x1).
go right - out of maze, go back.
go left (to S)
....
You are in an infinite loop! (one known draw back of DFS)
The StackOverflowError is usually an indication that this is the issue, the call stack is full from all the recursive calls - and an error is thrown.
To fix it, you need to maintain a visited set, and avoid revisitting already visited nodes. With this set, and the above maze (order of directions is right, left, down, ...) what will happen is:
go right (to x1)
go right - out of maze, go back.
go left (to S) - already visitted, go back.
go down (to E) - found target, return it.
A more advanced alternative is using Iterative Deepening DFS - which basically mean, you are limitting the length of the path to l, and iteratively increase this l. I'd ignore this alternative for this time, it is a bit more advanced.
As a side note, your algorithm is an implementation of DFS, which is complete with a visited set and in finite graphs (always finds a solution if one exists), but not optimal (does not guarantee to find the shortest path). To find the shortest path, you might want to use BFS instead.
Also: I assume the recursive call in the third line of the method is a leftover that is there for debugging. It shouldn't be there.
Related
I have used a DFS-algorithm for noting the moves needed to solve the maze. There's a startVertex and an endVertex. My code is as follows:
private void DFS(int vertex, boolean visited[], LinkedList<Move> output) {
visited[vertex] = true;
for (int neighbor: g.neighbors(vertex)) {
if (visited[neighbor] != true) {
if (neighbor == vertex + 1)
output.add(Move.RIGHT);
else if (neighbor == vertex - 1)
output.add(Move.LEFT);
else if (neighbor == vertex + Math.sqrt(g.size()))
output.add(Move.DOWN);
else
output.add(Move.UP);
if (neighbor == endVertex)
break;
DFS(neighbor, visited, output);
}
else {
output.removeLast();
}
}
}
I am using the removeLast() function when all the surrounding neighbors have been explored and thus that particular vertex remains of no use. But I think that the error lies there only.
The size of graph g is n*n because the original maze is a 2D square matrix with n rows and n columns.
You need to clear visited when leaving DFS (and the endVertex hasn't been found)
output.removeLast should be symmetrical to output.add
break only leaves the innermost loop. Is that what you want?
You probably want to let DFS return whether the endVertex was found, so you know the search can be stopped in higher layers
I'm trying to implement a solution to this problem but I am having some problems.
The problem is:
"There is a robot in the upper left hand corner of a grid with r rows and c columns. The robot can only move right or down and certain cell's are "off limits" meaning the robot cannot step on them. Design an algorithm to find a path for the robot from the top left to the bottom right."
The solution looks like this:
public static ArrayList<Point> getPath(boolean[][] maze){
if(maze == null || maze.length==0) return null;
ArrayList<Point> path = new ArrayList<Point>();
HashSet<Point> failedPoints = new HashSet<Point>();
if(getPath(maze, maze.length-1,maze[0].length-1,path,failedPoints)){
return path;
}
return null;
}
public static boolean getPath(boolean[][] maze, int row, int col,
ArrayList<Point> path, HashSet<Point> failedPoints){
/*if out of bounds or not available, return*/
if(col<0 || row<0 || !maze[row][col]){
return false;
}
Point p = new Point(row,col);
/*If we've already visited this cell return*/
if(failedPoints.contains(p)){
System.out.println("Worked");
return false;
}
boolean isAtOrigin = (row == 0) && (col == 0);
/*If there's a path from start to my current location, add my location.*/
if(isAtOrigin || getPath(maze,row,col -1, path, failedPoints) || getPath(maze,row-1, col, path,failedPoints)){
path.add(p);
return true;
}
failedPoints.add(p); //Cache result
return false;
}
What's confusing to me is the attempt at Dynamic Programming.
if(failedPoints.contains(p)) never evaluates to true.
I have overridden the equals and hashCode methods in my Point class so failedPoints.contains(object) evaluates to true whenever the object compared has the same row and col values.
Perhaps it has to do with the maze input i'm using:
boolean[][] maze = new boolean[4][4];
java.util.Arrays.fill(maze[0],true);
java.util.Arrays.fill(maze[1],true);
java.util.Arrays.fill(maze[2],true);
java.util.Arrays.fill(maze[3],true);
maze[0][1] = false;
maze[3][2] = false;
ArrayList<Point> path = getPath(maze);
But I'm not sure. In the end I don't see how failedPoints.contains(p) is saving my computer any execution steps
Here is the point class:
public class Point {
int row;
int col;
Point(int row1,int col1) {
row = row1;
col = col1;
}
public boolean equals(Object o) {
if (!(o instanceof Point)) return false;
Point comp = (Point) o;
return comp.row == row && comp.col == col;
}
public int hashCode() {
return row;
}
}
It's your maze's design.
This is your maze, according to the input you have written in the question:
E O O O
O O O O
O O X X
O O X S
You start at S and are trying to reach E, with X being off limit locations.
So, you see that with S being entirely covered with off limit points, there is no way you can reach E. And hence the very first point S is a failed point which is never re-used because the algorithm halts after the evaluation of S.
Perhaps if you would set the point in 0th row and 1st column as off limit, you will have multiple explorations that will reach this point and take advantage of caching to ascertain that this point cannot be used any further for exploring the maze.
UPDATE:
After you updated the maze, I realized that there are two issues with your implementation, not one.
Change the line,
if(isAtOrigin || getPath(maze,row,col -1, path, failedPoints) || getPath(maze,row-1, col, path,failedPoints))
to
if(isAtOrigin || getPath(maze,row-1,col, path, failedPoints) || getPath(maze,row,col-1, path,failedPoints))
and the code will actually work with the new maze.
The issue is that you are returning from the getPath() as soon as you find a path. And because you are first going to left and then going up, the point [0, 2] (which is a failed point) is not hit at all, and therefore not cached, and therefore not used either.
Changing the if condition causes your algorithm to first search up and then search left. This causes you to hit [0, 2] multiple times, resulting in it being cached as well as re-used in further path searches.
I work on a genetic algorithm for a robotic assembly line balancing problem (assigning assembly operations and robots to stations to minimize the cycle time for a given number of stations). The solution is represented by an ArrayList (configuration) which holds all the operations in the sequence assigned to different stations. Furthermore, I have two more ArrayLists (robotAssignment, operationPartition) which indicate where a new station starts and which robot is assigned to a station. For example, a solution candidate looks like this (configuration, robotAssignment, operationPartition from top to bottom):
Initial cycle time: 50.0
|2|7|3|9|1|5|4|6|8|10|
|2|1|3|2|
|0|2|5|7|
From this solution representation we know that operations 3, 9, and 1 are assigned to the second sation and robot 1 is used.
I need to keep track of the station an operation is assigned to. I tried a lot to store this in the Object Operation itself but I always ended up in problems and therefore I want to write a method that gives me the stations index of an operation.
Here is what I have coded so far:
// Get the station of an operation
public int getStation(Operation operation) {
int stationIndex = 0;
int position = configuration.indexOf(operation);
for (int i = 0; i < GA_RALBP.numberOfStations ; i++ ) {
if (i < GA_RALBP.numberOfStations - 1 && operationPartition.get(i) != null) {
if (isBetween(position, (int) operationPartition.get(i), (int) operationPartition.get(i + 1))) {
return stationIndex + 1;
} else {
stationIndex++;
}
}
else if (i >= GA_RALBP.numberOfStations - 1 && operationPartition.get(i) != null) {
if (isBetween(position, (int) operationPartition.get(i), configurationSize())) {
return stationIndex + 1;
}
}
}
return -1;
}
// Check if value x is between values left and right including left
public static boolean isBetween(int x, int left, int right) {
if (left <= x && x < right ) {
return true;
}
else {
return false;
}
}
However, this does not seem to be (a) very elegant and (b) if I have to do this for a large number of operations the runtime could become a problem. Has anoyone an idea how to solve this more efficiently?
Why not make the partitioning explicit (replaces your operationPartition) - something like:
Map<Integer, Integer> operationToStationMapping = new HashMap<>();
operationToStationMapping.put(2,0);
operationToStationMapping.put(7,0);
operationToStationMapping.put(3,2);
operationToStationMapping.put(9,2);
operationToStationMapping.put(1,2);
operationToStationMapping.put(5,5);
operationToStationMapping.put(6,7);
operationToStationMapping.put(8,-1);
operationToStationMapping.put(10,-1);
Then getStation() becomes:
getStation(int operation) {return operationToStationMapping.get(operation);}
I've created a Sudoku solver that will solve a Sudoku as a human might- by checking possibilities + definite values in squares corresponding to the square being checked.
(Source: http://pastebin.com/KVrXUDBF)
However, I would like to create a random Sudoku generator (from a blank grid), and so have decided to use a backtracking algorithm. I understand the concept of backtracking, but am confused about one thing:
How do I know which previous node to return to (and change) once I know a certain solution is not allowed?
Should I simply return to the previous node and cycle through all possibilities? (And then if this yields no correct answers, return to the value before, etc.). This seems like a viable method, but also quite inefficient. Is this the correct way of implementing a backtracking method or is there a better way to go about it?
Thanks in advance.
More can be found about backtracking here: http://en.wikipedia.org/wiki/Backtracking
Sudoku Puzzle can be reduced to graph coloring problem which can be solved using simple backtracking like assigning colors to node (1-9) till the there is no violation that all directly connected nodes have no same color.
Constructing Graph from Sudoku : -
There is an direct edge between two grid points if they are in same
row or column or square.
Backtracking :-
Assign one color (1-9) to node
Check if there is no other directly connected node with same color
If valid color move to next node.
else change the color and recheck.
If all color exhausted backtrack to previous node.
Do recursion till all nodes are color.
Once You are done with it you can start removing numbers from the grid at random till you think the problem is unsolvable if any more numbers are removed.
A simple way to generate random Sudoku is that
1) generate a random completing Sudoku, that is, generate random Sudoku no square is blank.
2) Remove numbers from squares of 1).
3) Solve Sudoku of 2). If there are many solutions, then add a number removed at 2).
If there are still many solutions, then repeat 3).
1) sample source code:
public int[][] generateRandomCompleteSudoku() {
int[][] sudoku = new int[10];
for(int i = 1; i <= 9; i++) {
sudoku[i] = new int[10];
Arrays.fill(sudoku[i], 0);
}
generateRandomCompleteSudoku(sudoku, 1, 1);
return sudoku;
}
private boolean generateRandomCompleteSudoku(int[][] sudoku, int x, int y) {
if(x > 9) {
x = 1;
y++;
}
//sudoku of the argument is completing sudoku.
//so return true
if(y > 9) {
return true;
}
// enumerate the possible numbers of the pos(x,y).
List<Integer> possibleNumbers = new ArrayList<Integer>();
for(int i = 1; i <= 9; i++) {
boolean possible = true;
//check i is a possible number.
//check there isn't i in the raw of y .
for(int j = 1; j <= x - 1; j++) {
if(sudoku[j][y] == i) {
possible = false;
break;
}
}
//check there isn't i in the column of x(omitted).
//check there isn't i in the group of x,y(omitted).
if(possible) {
possibleNumbers.add(i);
}
}
//sudoku is wrong so return false.(There is no solution of sudoku)
if(possibleNumbers.size() <= 0) {
return false;
}
Collections.shuffle(possibleNumbers);// This gives sudoku randomness.
for(Integer possibleNumber : possibleNumbers) {
sudoku[x][y] = possibleNumber;
// a sudoku is generated, so return true
if(generateRandomCompleteSudoku(sudoku, x + 1, y)) {
return true;
}
}
// No sudoku is generated, so return false
return false;
}
For a backtracking solution, the first step is to define the state. So for this problem, I think the most straightforward way is (x,y, blank , num) with x , y is the position of the current state, blank is the number of blank position left, and num is the value you want to fill in that position (from 0 to 9 and 0 means blank).
And the return type should be boolean, which determine whether the move is valid or not (which means is there any valid solution for this move).
So, the state transition is column by column, row by row: x, y to x , (y + 1) or x , y to (x + 1), 0.
Similarly, the blank will be from a -> a - 1-> ... 0.
We have a draft solution here:
public boolean move(int x, int y, int blank, int num, int[][]sudoku){
sudoku[x][y] = num;
//checking condition and return if x,y is the last position, code omitted
if(y == sudoku[x].length){
x++;
y = 0;
}else{
y++;
}
for(int i = 1; i < 10; i++){
if(move(x,y,blank,i,sudoku){//Backtrack here
return true;
}
}
if(blank > 0){
if(move(x,y,blank - 1, 0, sudoku){//Backtrack here
return true;
}
}
return false;
}
So when ever there is a false return from the current state, it will backtrack to the last state , and the last state will continue to check for the next num until it find a correct solution (or return false).
I have to create a program that finds all the possible ways of filling a square of size x by y. You place a block which takes up 2 spaces to completely fill.
The problem is I don't know how to code it to the point where you can remember the placements of each square. I can get it to where it fills the board completely once and maybe twice, but nothing past that. I also know that I'm supposed to use recursion to figure this out . Here is the code I started on so far. There is also a main method and I have the initial even/odd check working fine. This is the part I have no idea on.
public void recurDomino(int row, int column) {
if (Board[2][x - 1] != false) {
} else if(Board[1][x-1]!=false)
{
}
else {
for (int n=0; n < x - 1; n++) {
Board[row][column] = true;
Board[row][column+1] = true;
column++;
counter++;
}
recurDomino(1, 0);
recurDomino(2, 0);
}
}
Thank you for any help you guys can give me.
******************* EDIT ****************************************
I am a little confused still. I came up with this algorithm but I always get 2 for any value greater or equal to 2.
public boolean tryHorizontal(int row , int col){
if( row < 0 || row >= array[0].length-1)
return false;
else
return true;
}
public boolean tryVertical(int row, int col){
if( col < 0 || col >= 2 )
return false;
else
return true;
}
public boolean tryRowCol(int row, int col){
if(this.tryHorizontal(row, col) && this.tryVertical(row, col)){
return true;
}
else
return false;
}
public int findWays(int row, int col){
int n = 0;
if( !this.tryRowCol(row, col))
return 0;
else
n =+ 1 + this.findWays(row+1, col+1);
return n;
}
This recursive solution actually generates all the possible tiling of a general MxN board. It's more general than what your program requires, and therefore not optimized to just count the number of tiling of a 3xN board.
If you just want to count how many there are, you can use dynamic programming techniques and do this much faster. Also, having the number of rows fixed at 3 actually makes the problem considerably easier. Nonetheless, this general generative solution should be instructive.
public class Domino {
final int N;
final int M;
final char[][] board;
int count;
static final char EMPTY = 0;
Domino(int M, int N) {
this.M = M;
this.N = N;
board = new char[M][N]; // all EMPTY
this.count = 0;
generate(0, 0);
System.out.println(count);
}
void printBoard() {
String result = "";
for (char[] row : board) {
result += new String(row) + "\n";
}
System.out.println(result);
}
void generate(int r, int c) {
//... see next code block
}
public static void main(String[] args) {
new Domino(6, 6);
}
}
So here's the meat and potatoes:
void generate(int r, int c) {
// find next empty spot in column-major order
while (c < N && board[r][c] != EMPTY) {
if (++r == M) {
r = 0;
c++;
}
}
if (c == N) { // we're done!
count++;
printBoard();
return;
}
if (c < N - 1) {
board[r][c] = '<';
board[r][c+1] = '>';
generate(r, c);
board[r][c] = EMPTY;
board[r][c+1] = EMPTY;
}
if (r < M - 1 && board[r+1][c] == EMPTY) {
board[r][c] = 'A';
board[r+1][c] = 'V';
generate(r, c);
board[r][c] = EMPTY;
board[r+1][c] = EMPTY;
}
}
This excerpt from the last few lines of the output gives an example of a generated board, and the final count.
//... omitted
AA<><>
VVAA<>
AAVV<>
VVAA<>
<>VVAA
<><>VV
//... omitted
6728
Note that 6728 checks out with OEIS A004003.
A few things that you need to learn from this solutions are:
Clean-up after yourself! This is a very common pattern in recursive solution that modifies a mutable shared data. Feel free to do your thing, but then leave things as you found them, so others can do their thing.
Figure out a systematic way to explore the search space. In this case, dominoes are placed in column-major order, with its top-left corner as the reference point.
So hopefully you can learn something from this and adapt the techniques for your homework. Good luck!
Tip: if you comment out the printBoard line, you can generate all ~13 million boards for 8x8 in reasonable time. It'll definitely be much faster to just compute the number without having to generate and count them one by one, though.
Update!
Here's a recursive generator for 3xN boards. It doesn't use a shared mutable array, it just uses immutable strings instead. It makes the logic simpler (no clean up since you didn't make a mess!) and the code more readable (where and how the pieces are placed is visible!).
Since we're fixed at 3 rows, the logic is more explicit if we just have 3 mutually recursive functions.
public class Domino3xN {
static int count = 0;
public static void main(String[] args) {
addRow1(8, "", "", "");
System.out.println(count);
}
static void addRow1(int N, String row1, String row2, String row3) {
if (row1.length() == N && row2.length() == N && row3.length() == N) {
count++; // found one!
System.out.format("%s%n%s%n%s%n%n", row1, row2, row3);
return;
}
if (row1.length() > row2.length()) { // not my turn!
addRow2(N, row1, row2, row3);
return;
}
if (row1.length() < N - 1)
addRow2(N, row1 + "<>",
row2,
row3);
if (row2.length() == row1.length())
addRow3(N, row1 + "A",
row2 + "V",
row3);
}
static void addRow2(int N, String row1, String row2, String row3) {
if (row2.length() > row3.length()) { // not my turn!
addRow3(N, row1, row2, row3);
return;
}
if (row2.length() < N - 1)
addRow3(N, row1,
row2 + "<>",
row3);
if (row3.length() == row2.length())
addRow1(N, row1,
row2 + "A",
row3 + "V");
}
static void addRow3(int N, String row1, String row2, String row3) {
if (row3.length() == row2.length()) { // not my turn!
addRow1(N, row1, row2, row3);
return;
}
if (row3.length() < N - 1)
addRow1(N, row1,
row2,
row3 + "<>");
}
}
You don't often see 3 mutually recursive functions like this, so this should be educational.
One way of doing it is with the CSP (Constraint Satisfaction Problem) approach:
Consider every cell in the grid to be a variable, with 4 possible values (indicating the part of the domino it takes). Some assignments are obviously illegal. Legal assignments assign values to a "neighboring variable" as well. Your goal is to assign all the 3xN variables with legal values.
The recursion here can help you cover the state space easily. On each invocation, you try to assign a value to the next unasigned cell, by trying all the 4 options. After each successfull assignment, you can call the same method recursively, and then undo your last assignment (this way you don't have to clone anything - one copy of the grid data is enough).
--EDIT--
If you want to do it efficiently so that it works for large values on N in reasonable time, you will also have to think about optimizations, in order to discard some assignment attempts.
Here are some hints:
With a fixed-size board you can precompute the exact number of steps that each solution takes, so the termination criterion is trivial: you just check the nesting level.
Starting from one corner is a good idea, because it means that you can always find a field that can only be covered in two different ways (vertically or horizontally).
That means that you have a branching factor of only 2, and a recursion depth of 3*N/2, which is probably small enough that you can just clone the sstate of the board for each call (ordinarily you would construct new states incrementally from existing states to save space, but that is a bit harder to program).
In many states here will be more than one field that allows only two possibilities; with a clever strategy for choosing the next field, you can ensure that you will never find the same solution via two different paths, so you don't even have to check the solutions for duplicates.
The state of the board must record which fields are free and which fields are occupied, but also which fields are occupied by the same domino, so an array of int could do the trick.