I am trying to implement a 2 dimensional matrix as a maze. There is a starting point, an ending point (randomly chosen). And to make it little complicated, there are obstacles and agents. If the rat runs into an obstacle, it should backtrack and find the correct path. If it runs into an agent, it gets destroyed.
Here's a sample 4x4 matrix
1 7 1 1
2 1 1 0
1 0 1 0
1 1 1 9
Key: 0 is an obstacle, 2 is an agent, 7 is the starting point, 9 is the goal/ending point. 1 means that is is safe to move there.
The correct solution for this matrix would be:
0 1 1 0
0 0 1 0
0 0 1 0
0 0 1 1
But the rat is not intelligent (at least for this program) , so I am implementing a brute force algorithm, with random moves.
I have tried to implement this using a recursive function called mazeUtil().
Below is the function:
maze[][] is the randomized initial matrix that the rat moves through.
solution[][] is the solution matrix that will keep track of the moves.
(x, y) is the current position in the grid
n is the size of the matrix (it is a square matrix).
public static void mazeUtil(int maze[][], int solution[][], int x, int y, int n)
{
if(x == goal[0] && y == goal[1])
{
solution[x][y] = 1;
return;
}
int check = moveCheck(maze, x, y, n);
//moveCheck() return 0 for Obstacle, 1 for safe path, 2 for agent, 7 for starting point (also safe path), 9 for goal (safe path)
if (check == 2){
solution[x][y] = 1;
out.println("Oops! Ran into an agent!");
return;
}
else if(check == 0)
{
//What should I put here?
}
else if(check == 1 || check == 7 || check == 9)
{
solution[x][y] = 1;
Random newRandom = new Random();
int temp = newRandom.nextInt(3);
if(temp == 0){ //move up if possible? x--
if(x > 0)
mazeUtil(maze, solution, x-1, y, n);
else
mazeUtil(maze, solution, x+1, y, n);
}
else if (temp == 1){
if (x < n-1)
mazeUtil(maze, solution, x+1, y, n);
else
mazeUtil(maze, solution, x-1, y, n);
}
else if(temp == 2){
if (y < n-1)
mazeUtil(maze, solution, x, y+1, n);
else
mazeUtil(maze, solution, x,y-1, n);
}
else if (temp == 3){
if (y > 0)
mazeUtil(maze, solution, x, y-1, n);
else
mazeUtil(maze, solution, x, y+1, n);
}
}
}
I have to randomize the moves and that's why i have used random function. My function works quite well if it runs into an agent (2). I have also prevented the rat from going out of boundary. And it doesn't have any problem going through the safe path (1). But the problem is when it hits an obstacle. I'm thinking about backtracking. How do I add that into my function? Like save the last step, and do the reverse? And it is quite possible that there is no solution in the maze like this one
7 0 0 9
2 0 1 1
0 1 0 0
1 2 0 1
It would hit an obstacle if it goes right, and hit an agent if it goes down. It cannot move diagonally.
That brings me to my second question, how would I terminate my recursive function in that case.
At this point the only time it terminates is when it reaches the goal or hits an agent.
Any help would be appreciated. Thanks in advance
Well, let's imagine I need to solve the same problem by the same way you are solving it.
(I think the best solution for it is Path finding, as already mentioned in comments).
I will create
class Point{
public int x;
public int y;
}
and store coordinates in it.
I will store all points the rat visited in List<Point> path
In this solution you do not have problems with previous point (it is the last point in list)
As for algorithm termination -- you use algorithm with randoms. So you can't be sure that your rat will solve the simplest maze like
7 1 1
1 1 1
1 1 1
it is possible that rat will move from (0,0) to (1,0) and from (1,0) to (0,0) forever.
So, let's again imagine that I need to improve your algorithm instead of using good one.
I will store number of times the rat returned back from obstacle or visited the point in path list.
If this number > 4 I will command to my rat return back to the original point (point 7). And start the journey again.
If the rat need to return back, for example 10 times, the algorithm terminates.
Again, your algorithm is funny, and it should be interesting to see how the rat moves but it does not solve the problem. It will not work on big mazes.
Try to implement path finding. If you will have problems -- ask questions.
Good luck!
A quick point on style, to save some typing later: maze[][], solution[][] and n are all effectively global, and do not change between recursive calls (maze and solution are just passed as references to the same arrays, and n never changes). This is purely style, but you can write this as:
private static int[][] maze;
private static int[][] solution;
private static int n;
public static void mazeUtil(int x, int y) {
...
}
So on to your solution: the first point is I don't see how you know when you've reached the goal; your mazeUtil function does not return anything. For this kind of recursion, a general approach is for your solver function to return a boolean: true if the goal has been reached and false if not. Once you get a true, you just pass it back all the way up the call stack. Each time you get a false, you backtrack to the next solution.
So I'd suggest:
public static boolean mazeUtil(int x, int y) {
// return true if goal found, false otherwise
...
}
Next, I'm not sure what the practical difference between an agent and an obstacle is: running in to either causes you to backtrack. So I'd think that bit of code would be:
if (check == 2) {
out.println("Oops! Ran into an agent!");
return false;
}
if (check == 0)
out.println("Oops! Ran into an obstacle!");
return false;
}
Then the recursive bit: one point here is you do not ever reset the solution to 0 for failed attempts (actually, as the final algorithm will never backtrack more than a single step this is not actually that important, but it's good to illustrate the general approach). Given what we have so far, this should now be something like:
if (check == 9) {
out.println("Found the goal!");
return true;
}
if (check == 1 || check == 7) {
// add current position to solution
solution[x][y] = 1;
// generate random move within bounds
int nextX = ...
int nextY = ...
if (mazeUtil(nextX, nextY)) {
// we've found the solution, so just return up the call stack
return true;
}
// this attempt failed, so reset the solution array before returning
solution[x][y] = 0;
return false;
}
// shouldn't ever get here...
throw new IllegalStateException("moveCheck returned unexpected value: " + check);
Right, so far so good, but there's still a problem. As soon as one of the mazeUtil calls returns a value (either true or false) it will return that all the way up the calls stack. So if you happen to find the exit before an agent or an obstacle, all good, but that's quite unlikely. So instead of trying a single move when recursing, you need to try all possible moves.
WIth a supporting class Point, containing a simple x and y pair:
if (check == 1 || check == 7) {
// add current position to solution
solution[x][y] = 1;
// generate an array of all up/down/left/right points that are within bounds
// - for a random path need to randomise the order of the points
Point[] points = ...
for (Point next : points) {
if (mazeUtil(next.x, next.y)) {
// we've found the solution, so just return up the call stack
return true;
}
}
// this attempt failed, so reset the solution array before returning
solution[x][y] = 0;
return false;
}
And I think that's about as far as you can go with a totally ignorant rat! To see how this works, consider the following maze:
7 1
0 9
Starting at "7", possible moves are Down and Right.
If you try Down first, it returns false, so the only option left is
Right, so you end up on the "1".
If you try Right first, you still end up on the "1".
From the "1", possible moves are Down and Left:
If you try Down first, it returns true, which bubbles up the call stack - success!
If you try Left first, you end up on the "7", so recurse to the previous step.
And that's all that can ever happen. So using * for a return-false-backtrack, and ! for a success, any of the following are possible:
R-D!
R-L-D*-R-D!
R-L-R-L-R-L-R-L (keep going for a long, long time....) R-L-R-D!
So for a solvable maze, and a truly random generator, this will eventually solve the maze, although it could take a very long time. Something to note with this though, is it does not really backtrack that much: only ever a single step from a 2 or 0 node.
However, there's still the problem of the unsolveable maze, and I don't think that is possible given a totally ignorant rat. The reason for this is that for a brute force recursion like this, there are only two possible termination conditions:
The goal has been found.
All possible paths have been tried.
And with a totally ignorant rat, there is no way to detect the second!
Consider the following maze:
7 1 1 1
0 0 0 0
0 0 0 0
1 1 1 9
The totally ignorant rat will just wander left and right across the top row forever, and so the program will never terminate!
The solution to this is that the rat must be at least a bit intelligent, and remember where it has been (which will also make the solveable maze run quicker in most cases and backtrack along entire paths instead of only for single nodes). However, this answer is getting a bit too long already, so if you're interested in that I'll refer you to my other maze-solving answer here: Java Recursive Maze Solver problems
Oh, just two final points on Random:
You don't need to create a new Random each time - just create a
global one and call nextInt each time.
nextInt(n) returns between 0 (inclusive) and n (exclusive), so you
need nextInt(4) not nextInt(3).
Hope this all helps!
if you want to move in random, u need to know the states you've been already in them, so u will need a tree, otherwise u can keep the most left path when the rat is in multi way place.
now lets think of recursive + random. it can not be that hard. you can have a function that returns the list of points it has been in them, and get correct position as input, there is a bit of problem and the idiot rat can got back the way he already came from, so lets solve it with adding previous point as another input for our function.
every thing in place. now we wana know if the idiot rat runs into a dead path or an agent. how about making 2 exceptions for this situations and handling them in recursive function??
well, i don't think there will be any more problems on way. actually i'm temped to try it myselft. that would be fun :D
good luck with the idiot rat
I'd like to do some analysis of your algorithm design before proposing a solution.
You mention that you want to use a random walk algorithm. No problem with that it's a perfectly acceptable (though not necessarily efficient) way to look for a path. However you need to be aware that it has some implications.
In general random walk will not tell you when there is no solution. If you just keep trying paths at random you will never exhaust the search tree.
If this is unacceptable (i.e. it needs to be able to halt when there is no soltuion) then you need to keep a record of paths already attempted and randomise only those not yet attempted.
Random walk won't necessarily find the optimal solution unless there is only one solution. In other words if there are loops / multiple paths in your maze then there's no guarantee you are finding the fastest.
I can't actually see the difference between agents and obstacles in your problem. In both cases you need to backtrack and find another path. If there is a difference then you'll need to point it out.
So assuming your maze could have zero or more successful paths and you are not looking for the optimal path (in which case you really should use A* or similar), the structure of a solution should look something like:
public List<Position> findPath(Set<Position> closedSet, Position from, Position to) {
if (from.equals(to))
return List.of(to);
while (from.hasNeighboursNotIn(closedSet)) {
Position pos = from.getRandomNeighbourNotIn(closedSet);
closedSet.add(pos);
List<Position> path = findPath(closedSet, pos, to);
if (!path.isEmpty())
return List.of(pos, path);
}
closedSet.add(from);
return Collection.EMPTY_LIST;
}
This uses lots of pseudo-code (e.g. there is no List.of(item, list)) but you get the idea.
Related
I looked up the solution to this problem yesterday and tried to solve on my own today but found myself trying to solve this problem in a different way. I feel I may be overcomplicating the problem but I still want an answer to my possible solution just because it is bugging me to know (I am sure everyone has experienced this at some point or another). Anyway here is the problem:
https://www.hackerrank.com/challenges/ctci-array-left-rotation/problem?h_l=interview&playlist_slugs%5B%5D=interview-preparation-kit&playlist_slugs%5B%5D=arrays
My idea is that you would first check to see if your array length was equal to the rotations you want then you would simply return the original. There is no work needed to be done.
My next idea would be to check to see if our rotations is greater than our array length. If this is the case, we can either do rotations - array length or ABS VALUE(array length - rotations), which gives us the same result. We can reassign this value to D.
Next, we can create a case to rotate right instead of left. When your rotation is greater than your array length / 2, then we would not to rotate left since we are doing extra work. We instead would want to rotate right. For example:
Array Length 4
Rotations 3 (LEFT)
We can simply rotate right once instead of rotating left 3 times. We could set the rotateRight boolean to true (otherwise set to false which indicated to rotateLeft as normal)
Anyway this is the part I get caught on. I am unsure of how to rotate my elements here. I was thinking of returning a new array. How can I get the correct values for my new array? I am facing issues with IndexOutOfBounds exceptions. Can I also use try catches in this example or is it overkill?
Here is the code I have currently it should match my thoughts from up above:
static int[] rotLeft(int[] a, int d) {
int aLength = a.length;
int counter = 0;
int[] newArray = new int[aLength];
boolean rotateRight = false;
if (aLength == d) {
return a;
}
if (a.length - d < 0) {
d = Math.abs(a.length - d);
}
if(d > a.length/2) {
rotateRight = true;
}
return newArray;
}
If you need any more info let me know.
There is little benefit to trying to simplify the maths, if it leads to a harder-to-write program -- especially since you do not want to rotate the array at all, and can simply place the correct values in the correct places directly.
If the old position of element i was i, after d left-rotations of an array of size len, its new position will be (i-d)%len. If d == len+1 this is indeed equivalent to (i+1)%len -- easier for humans, but computers calculate either expression just as happily.
So the suggested code is:
static int[] rotLeft(int[] a, int d) {
int[] b = new int[a.length];
for (int s=d, t=0; t<a.length; s++, t++) {
// t is target position; s is source position
b[t] = a[s%a.length];
}
return b;
}
Note: code is untested
i am writing the function to check if the given value is included in the matrix in . This matrix has the following properties:
•Integers in each row are sorted in ascending from left to right.
•Integers in each column are sorted in ascending from top to bottom
public static boolean searchMatrix(int target, int[][] matrix)
{
for(int i = 0;i <= matrix[0].length;i++)
{
for (int j=i; j<matrix.length;j++)
{
if(target == matrix[i][j])
return true;
}
}
return false;
}
i want to know weather this program has time complexity of O(N).
if not what changes should i make to get into O(N).
I think the search can be done in linear time. Consider the following 4×4 matrix as a visual:
1 2 4 6
2 3 5 7 ascending from left to right
3 4 6 8 and from top to bottom
4 5 6 9
If we were searching for the value 5 we could begin in the upper left, and then walk to the right until we have either found the value, or encountered a number which is greater than the target of 5. In this case, we hit 6. Then, we can rollback to 4, and advance down to a higher row. It is guaranteed that every previous value in the first row is less than the target and that every value in the next row from that column onwards is greater than the value on the first row.
This is a roughly linear approach. A good analogy would be walking around the perimeter of a mountain, looking for a certain elevation. If at each spot we either don't find the height we want, or find only points too high, we keep walking.
The way you have it written (brute force computation) has a worst case time complexity of O(N^2). Since you say that the arrays are sorted, you can instead implement binary search which will have a worst case time complexity of N(2*log(N)).
Assuming a n x m matrix, your algorithm is O(n * m), because it (potentially) iterates all rows and columns (ie all elements).
However, there exists an algorithm that is O(log(m + n)).
Because this is for an on-line coding interview (I am psychic), I will give you hints only:
Given elements at coordinate (x, y), what can know about where the target might be?
What could you do if you treated x and y separately?
you say the matrix is sorted ,may you can use binary search to find the target . and use two individual one layer loop , firstly search row ,then column.it's o(N/2).
As stated your algorithm is O(N*M) or O(N^2) for a square matrix.
You can do it with a single loop:
Basically starting from the top right you check the cell if the number is too big move left if the number is too small move down. If you fall off the edge on either side the number's not there.
boolean searchMatrix(int target, int[][] mat)
{
int i = 0, j = mat[0].length;
while (i < mat.length && j >= 0)
{
if (mat[i][j] == target)
{
return true;
}
else if (mat[i][j] < target)
{
i++;
}
else
{
j--;
}
}
return false;
}
I'm trying to work out the "towers of hanoi" problem, which moves stacks of disks organized from smallest to largest from a start stack to a destination stack, by means of an auxiliary stack without ever placing a larger disk on top of a smaller disk.
I was given the algorithim:
If numberDisks == 1:
Display “Move the top disk from S to D”.
Else
Move(numberDisks -1, ‘S’, ‘A’, ‘D’);
Move(1, ‘S’, ‘D’, ‘A’);
Move(numberDisks -1, ‘A’, ‘D’, ‘S’);
However this seems to differ from most other examples which seem to work without using Move(1, ‘S’, ‘D’, ‘A’); in the recursive function.
As my code stands, I seem repeat the base case for every move, and im not sure how to structure my print statements to give the proper output which should look like:
Move disk 1 from S to D
Move disk 2 from S to A
Move disk 1 from D to A
Move disk 3 from S to D
Move disk 1 from A to S
Move disk 2 from A to D
Move disk 1 from S to D
When trying to move 3 disks.
// Recursively solve Towers of Hanoi puzzle
public static void main(String[] args) {
if (handleArguments(args)) {
System.out.println("numDisks is ok");
int numDisks = Integer.parseInt(args[0]);
Move(numDisks,'s', 'a', 'd' );
}
}
// recursive case
public static void Move(int disks, char start, char aux, char destination) {
// base case
if (disks == 1) {
System.out.println("Move disk 1 from S to D");
// if number of disks is 2 or greater
} else if(disks > 1) {
Move(disks - 1, start, aux, destination);
System.out.println("move disk " + disks + " from " + start + " to " + destination);
Move(1, start, destination, aux);
Move(disks - 1, aux, destination, start);
}
}
First thing: Understand the algorithm for moving n discs (from S to D, with A)
If there is only one disc to move, just move it then stop*.
Move n - 1 discs from S to A, with D.
Move nth disc from S to D
Move n - 1 discs from A to D, with S.
*Equally: If there are 0 discs, just stop. (Some would argue that this is the superior termination condition because, in your code, it will prevent the print statement when there is one from being a special case, it will be handled naturally by the print statement you cover step 3 with. When, for example, you decide to change this method to return a list of the steps instead of printing it, this change will only have to be applied in one place)
You mention that "I seem repeat the base case for every move." If you look at your code, and compare to my statements above. You will see that you call Move(1, start, destination, aux); between my steps 3 and 4. This is why you are repeating your base case, because you are explicitly calling, repeating your base case, but it doesn't make any sense to.
The other main problem I can see:
System.out.println("Move disk 1 from S to D"); will always print 'S' and 'D', in that order, when often you will need to specify a different move, ensure to use the arguments for this statement.
I don't think that there is anything else, but try it and see.
In response to the example you were given, in the start of your post. It produces subtly different output than your version.
Yours specifies (or attempts to) which size disc should be moved at each step, the example only specifies which stack to move a disc from and to, regardless of its size.
The recursive call with 1 as its argument in the middle there is to print the move instruction for moving the final disc in the stack (my step 3).
I'm making a SudokuSolver for a class, and I'm having trouble with the solve method. My current solution uses recursive backtracking (I think).
Assignment Requirements
int solve() -- tries to solve the puzzle using the strategy described above. Returns the number of solutions.
(The strategy described above)
When assigning a number to a spot, never assign a number that, at that moment, conflicts with the spot's row, column, or square. We are up-front careful about assigning legal numbers to a spot, rather than assigning any number 1..9 and finding the problem later in the recursion. Assume that the initial grid is all legal, and make only legal spot assignments thereafter.
Pseudocode Idea
I can follow this iteratively for a small input. For example, say I have to unsolved cells Cell #1 and Cell #2. #1 has possibilities { 1, 3 } and #2 has possibilities { 2, 3 }. I would then
set 1 to 1
set 2 to 2
hasConflicts? 0 : 1
set 2 to 3
hasConflicts? 0 : 1
set 1 to 3
set 2 to 2
hasConflicts? 0 : 1
set 2 to 3
hasConflicts? 0 : 1
Actual Code
public int solve() {
long startTime = System.currentTimeMillis();
int result = 0;
if (!hasConflicts()) {
Queue<VariableCell> unsolved = getUnsolved();
reduceUnsolvedPossibilities(unsolved); // Gets the possibilities down from all of 1-9
if (!hasConflicts()) {
result = solveRec(unsolved);
}
}
mElapsedTime = System.currentTimeMillis() - startTime;
return result;
}
protected int solveRec(Queue<VariableCell> unsolved) {
if (unsolved.isEmpty()) {
return (hasConflicts()) ? 0 : 1;
}
int result = 0;
VariableCell cell = unsolved.remove();
Iterator<String> possibilityIt = cell.getPossibilities().iterator();
while (possibilityIt.hasNext()) {
cell.setSymbol(possibilityIt.next());
if (hasConflicts()) {
possibilityIt.remove();
} else {
++result;
}
}
return result + solveRec(unsolved);
}
Test Results
testSolveSingleSolution
expected 1, actual 1
testSolveSolved
expected 1, actual 1
testSolveUnsolvable
expected 0, actual 0
testSolveMultiSolutions
expected 2, actual 7 // MAJOR PROBLEM!
Some Good Explanations of Recursive Backtracking
This answer to StackOverflow - Recursive solution to Sudoku generator
This answer to StackOverflow - BackTracking in a maze
This answer to StackOverflow - Backtracking algorithm for prime sequence
This answer to StackOverflow - How to find the first solution only with this backtracking
The Wikipedia article on Backtracking
Recursive Backtracking Explanation
Question
I've done recursive backtracking before, I've looked at all those links above and more, and I'm still having trouble. I think the problem lies in my thinking about how to solve this. (See Pseudocode Idea.) Is it appropriate to use recursive backtracking for an exhaustive search? Is the backtracking right but the implementation wrong? Is there a better algorithm I can use than recursive backtracking?
This looks like an implementation problem. Check the block where you're incrementing result. Do you really want to increment for each valid value of that cell? And for that matter overwrite the older valid value if there are several that are valid?
Here is the recursive version of the staircase problem (There are N stairs, a person standing at the bottom wants to reach the top. The person can climb either 1 stair, 2 stairs or 3 stairs at a time. Count the number of different ways the person can reach the top.)
public static int findStep(int n)
{
if (n == 1 || n == 0)
return 1;
else if (n == 2)
return 2;
else
return findStep(n - 3) +
findStep(n - 2) +
findStep(n - 1);
}
My question is, why we are returning 1 when n=0 ??
To me, n=0 means there are no more stairs so it should return 0, but if I do so then the program doesn't work for other non-zero inputs. I saw similar questions in this site but non of those explain why we are returning 1 when there are no more stairs.
This is a selection problem. Think of the recurrence as the number of ways to select and order a combination of zero or more 1's, zero or more 2's, and zero or more 3's, that will together sum to n. There is only one way to make such a selection for n = 0: select none.
In this code n=0 means in the last step n was equal to 1or 2 or 3. in other words :
n-1=0 which means in the last step n=1, so there is one way to reach the top of stairs.
n-3=0 which means in the last step n=3, so one way to reach the top of stairs is to make 3 steps.
My question is, why we are returning 1 when n=0 ??
It means, there is only one possible way to reach 1st stair. You can understand more about it by going through https://medium.com/trick-the-interviwer/the-staircase-problem-9840b11201a5