Android Flow game filling algorithm - java

According to my question Java algorithm filling cells like an `Android - Flow` game
Suppose i have four points(two pairs) how i can check is the exist combination of pathes between points that filling all game board?
Like an right image, but with four points ( two pairs ).
I need to check can i fill all game board with two arcs(path).
Now i stopped after filling the structure :
private static void buildGrid(int gridResolution) {
for (int i = 1; i < 3; i++) {
for (int j = 0; j < gridResolution; j++) {
Node node = new Node();
if (startPoint1.x == i && startPoint1.y == j) {
node.point = new PointM(new Point(i, j), 1);
startNode1 = node;
} else if (startPoint2.x == i && startPoint2.y == j) {
node.point = new PointM(new Point(i, j), 1);
startNode2 = node;
} else if (endPoint1.x == i && endPoint1.y == j) {
node.point = new PointM(new Point(i, j), 2);
endNode1 = node;
} else if (endPoint2.x == i && endPoint2.y == j) {
node.point = new PointM(new Point(i, j), 2);
endNode2 = node;
} else {
node.point = new PointM(new Point(i, j), 0);
}
nodes[i][j] = node;
Node leftNode = getLeftNode(i, j);
Node topNode = getTopNode(i, j);
if (leftNode != null) {
node.left = leftNode;
leftNode.right = node;
}
if (topNode != null) {
node.top = topNode;
topNode.bottom = node.top;
}
}
}
}
private static Node getTopNode(int i, int j) {
return nodes[i - 1][j];
}
private static Node getLeftNode(int i, int j) {
if (j - 1 > 0)
return nodes[i][j - 1];
else return null;
}
private static class Node {
public PointM point;
public Node left;
public Node right;
public Node top;
public Node bottom;
public boolean isChecked;
}
And i doesn't know what i need to do after that. I stuck on this moment. As best and will circumvent this table. Perhaps it is what the algorithm?

Personally, for building-grid purpose I'd invert your approach. So, instead of checking if for each pair a proper path exists, we will create grid which satisfies this condition.
So, the algorithm would look like this:
Create 1st path using unmarked points. Then mark all points of path. Insert coins at starting and ending point of path.
Create 2nd path using unmarked points. Then mark all points of path. Insert coins at starting and ending point of path.
...
Stop when all point are marked.
Then you will have grid where for each pair, there is a proper path.
Here is an example of this algorithm:

Related

PriorityQueue implementation in Java with support for changePriority operation

I require an implementation of a Priority queue that allows decrease priority operation to allow for an efficient implementation for Prim's and Dijkstra's algorithm.
I've coded up a minHeap implementation using a HashMap to store the indices of elements in my heap.
The problem I'm working on requires the computation of the total weight of the minimum spanning tree obtained by using Prim's algorithm. While my implementation works for most test cases upto 200 nodes, I'm still getting the incorrect output for many larger test cases.
It is my understanding that such minheap based implementations of Priority queues using HashMaps are common, if I am wrong in my assumption, please provide the more suitable approach to this problem.
I've been trying to debug my code for 2 days now and it seems the only way to fix it would be to compare it with a correctly functioning implementation.
Therefore, can someone please share such a PriorityQueue implementation using HashMap in java.
Even though I've tried a lot of test cases and for all the ones I can trace on my own(upto 30 nodes) I've gotten correct answers so far, but if there are some specific boundary test cases that could help me identify the problem, that too will be great.
Here is my code, I understand debugging it will be time consuming for anyone else, but if there is something obvious I've missed and someone with more expertise can point out the mistake, that would be most appreciated.
import java.util.HashMap;
import java.util.NoSuchElementException;
public class Heap<Key extends Comparable<Key>> {
private Key[] heap;
private int maxN, n;
private HashMap<Key, Integer> map;
#SuppressWarnings("unchecked")
public Heap(int maxN) {
if(maxN < 0 ) throw new IllegalArgumentException();
this.maxN = maxN;
n = 0;
heap = (Key[]) new Comparable[maxN];
map = new HashMap<>(maxN);
}
boolean isEmpty() {
return n == 0;
}
boolean insert(Key e) {
if(n +1 > maxN) throw new IllegalArgumentException("maximum capacity reached " + maxN);
heap[n] = e;
map.put(e,n);
int i = n++;
while ( (i+1)/2 - 1 >= 0){
if ( e.compareTo(heap[(i+1)/2 - 1]) < 0 ) {
swap(i, (i+1)/2 - 1);
i = (i+1)/2 - 1;
}
else
break;
}
return true;
}
Key extractMin() {
if(n == 0) throw new NoSuchElementException("Priority queue underflow ");
Key min = heap[0];
swap(0, n-1);
map.remove(min);
n--;
int j = 0, s;
while(j <= (n/2)-1){
if(j == (n/2)-1 && n == (j+1)*2 )
s = (j+1)*2 - 1;
else
s = heap[(j+1)*2 - 1].compareTo(heap[(j+1)*2]) < 0 ? (j+1)*2 - 1 : (j+1)*2;
if(heap[j].compareTo(heap[s]) > 0 ){
swap(j, s);
j = s;
}
else break;
}
return min;
}
Key delete(Key e){
if(!map.containsKey(e)) throw new NoSuchElementException(e+"does not exist ");
int j = map.get(e), s;
Key del = e;
swap(j, n-1);
map.remove(e);
n--;
while( j <= n/2 - 1){
if(j == (n/2)-1 && n == (j+1)*2)
s = (j+1)*2 - 1;
else
s = heap[(j+1)*2 - 1].compareTo(heap[(j+1)*2]) < 0 ? (j+1)*2 - 1 : (j+1)*2;
if(heap[j].compareTo(heap[s]) > 0 ){
swap(j, s);
j = s;
}
else break;
}
return del;
}
boolean decreasePriority(Key e){
if(n == 0)
return insert(e);
if(map.containsKey(e))
delete(e);
return insert(e);
}
private void swap(int i, int j) {
Key t = heap[i];
heap[i] = heap[j];
heap[j] = t;
map.replace(heap[i], i);
map.replace(heap[j], j);
}
#Override
public String toString() {
String res = "[";
int i;
for (i = 0; i < n-1; i++){
res += heap[i] + ", ";
}
res += heap[i]+"]";
return res;
}
}
I think the problem is in your delete method. Your code does this:
swap item to be removed with the last item in the heap
reduce heap count
push the new item down the heap
You're making the assumption that heap[j] < heap[n-1]. That's not a valid assumption. Consider this heap:
1
6 2
7 8 3
If you delete the node with value 7, the value 3 replaces it:
1
6 2
3 8
You now have to move it up the tree to make a valid heap:
1
3 2
6 8
The key here is that if the item you're replacing is in a different subtree than the last item in the heap, it's possible that the replacement node will be smaller than the parent of the replaced node.
If you're removing an item from the middle of the heap, you swap the item with the last, then you have to check whether the replacement node moves up or down.
Something you should consider, though, is that to change an item's priority, you don't have to delete and re-add. All you have to do is change the priority and then adjust the item's position appropriately: move up or down to put it in its new position.
The delete method was incorrect, I was using the same procedure for arbitrary deletes as for extractMin, which did not take into account the fact that the element I replace the key to be deleted with could possibly go both up or down the heap. Using swim() and sink() methods I have rectified this error. Also to change priority deletion and insertion are not required, and a simple call to both swim and sink is sufficient.(only swim if only decreasing priority and only sink if only increasing).
import java.util.HashMap;
import java.util.NoSuchElementException;
public class Heap<Key extends Comparable<Key>> {
private Key[] heap;
private int maxN, n;
private HashMap<Key, Integer> map;
#SuppressWarnings("unchecked")
public Heap(int maxN) {
if(maxN < 0 ) throw new IllegalArgumentException();
this.maxN = maxN;
n = 0;
heap = (Key[]) new Comparable[maxN];
map = new HashMap<>(maxN);
}
boolean isEmpty() {
return n == 0;
}
boolean insert(Key e) {
if(n +1 > maxN) throw new IllegalArgumentException("maximum capacity reached " + maxN);
heap[n] = e;
map.put(e,n);
int i = n++;
swim(i);
return true;
}
Key extractMin() {
if(n == 0) throw new NoSuchElementException("Priority queue underflow ");
Key min = heap[0];
swap(0, n-1);
map.remove(min);
n--;
sink(0);
return min;
}
void delete(Key e){
if(!map.containsKey(e)) throw new NoSuchElementException(e+" does not exist ");
int j = map.get(e);
swap(j, n-1);
map.remove(e);
n--;
if(!swim(j))
sink(j);
}
void decreasePriority(Key e){
if(map.containsKey(e)){
int j = map.get(e);
swim(j);
}
else insert(e);
}
private void swap(int i, int j) {
Key t = heap[i];
heap[i] = heap[j];
heap[j] = t;
map.replace(heap[i], i);
map.replace(heap[j], j);
}
private boolean swim(int j){
boolean change = false;
int parent;
while( (parent = (j-1)/2 ) >= 0){
if(heap[j].compareTo(heap[parent]) < 0){
swap(j,parent);
j = parent;
change = true;
}
else break;
}
return change;
}
private void sink(int j){
while(j <= n/2 - 1){
int leftChild = j*2 + 1, rightChild = leftChild + 1, s;
if(rightChild >= n)
s = leftChild;
else
s = heap[leftChild].compareTo(heap[rightChild]) < 0 ? leftChild : rightChild;
if(heap[j].compareTo(heap[s]) > 0){
swap(j,s);
j = s;
}
else break;
}
}
#Override
public String toString() {
String res = "[";
int i;
for (i = 0; i < n-1; i++){
res += heap[i] + ", ";
}
res += heap[i]+"]";
return res;
}
}
Edit: Be careful with your class comparator.

Trying to implement min-heap using logic of max-heap

I am trying to implement min-heap which includes methods like insert,delete and heap sort.I am using implementation of max-heap and trying to convert it to min-heap.But,i am having some minor issues.It's a very straight-forward method ,but i am missing something,which i am not able to get.
This is the Helper Max-heap implementation i am using:
public void trickleDown(int index)
{
int largerChild;
Node top = heapArray[index]; // save root
while(index < currentSize/2) // while node has at
{ // least one child,
int leftChild = 2*index+1;
int rightChild = leftChild+1;
// find larger child
if( rightChild < currentSize && // (rightChild exists?)
heapArray[leftChild].getKey() <
heapArray[rightChild].getKey() )
largerChild = rightChild;
else
largerChild = leftChild;
// top >= largerChild?
if(top.getKey() >= heapArray[largerChild].getKey())
break;
// shift child up
heapArray[index] = heapArray[largerChild];
index = largerChild; // go down
} // end while
heapArray[index] = top; // index <- root
} // end trickleDown()
/////// My Implementation
/** Removes the top element of the heap and returns it.
*
* Complexity: O(log n)
* #return Top (min/max) element of the heap.
* #throws IllegalStateException if the heap is empty.
*/
T remove() {
if (size == 0) {
throw new IllegalStateException();
}
Comparable root = data[0];
data[0] = data[size-1];
size--;
trickleDown(0);
return (T) root;
}
private void trickleDown(int i) {
int largerChild;
Comparable top = data[i]; // save root
while(i > size/2 ) // not on bottom row{
int leftChild = left(i);
int rightChild = right(i);
if(rightChild > size && data[left(i)].compareTo(data[right(i)]) < 0 )
largerChild = leftChild;
else
largerChild = rightChild;
if(data[i].compareTo(data[right(i)]) <= 0 )
break;
data[i] = data[largerChild];
i = largerChild;
}
data[i] = top;
}
///// Test File
void checkHeapOrder(MinHeap h) {
assertTrue(h != null);
for(int i = 1; i < h.size() / 2; ++i)
assertTrue("Heap order property is broken at element at position "
+ i,
h.data[i].compareTo(h.data[i*2]) < 0 &&
h.data[i].compareTo(h.data[i*2 + 1]) < 0);
}
#Test
public void testRemove() {
System.out.println("remove");
MinHeap h = new MinHeap(10);
boolean throws_exception = false;
try {
h.remove();
} catch (IllegalStateException e) {
throws_exception = true;
} catch (Throwable e) {
}
assertTrue("remove throws an exception when empty", throws_exception);
// Permutation of 0...9
int[] input = { 0, 5, 9, 2, 3, 1, 6, 8, 7, 4 };
for(int i : input)
h.insert(i);
assertTrue(h.isFull());
for(int i = 10; i > 0; --i) {
assertEquals(h.size(), i);
Integer x = (Integer)h.remove();
assertEquals(x, new Integer(10-i)); // Items are removed in correct order
checkHeapOrder(h);
}
testRemove Failed: expected<0> but was <1>
I am pretty sure that the code is simple and i have tried to change everything from max to min,but just missing on with something,which i am having a hard time figuring out.

Java path finding simplified

Background: I am making a 2D moba game and i need pathfind for all the monsters in the game. I want to give a startPos and a endPos and have the monster travel there avoiding objects.
Question:
I have been trying to implement path finding into my game for awhile now and i just cant see to get it working. All i want is some method/class where i can give it a 2d array of values (ie. true = occupied & false = free), startPos, endPos and it gives me a list of moves to get to the end. All my implementations have failed thus far. Can anyone help by giving me code that is easy to implement?
Note:
So far i have tried implementing A and it either ignored walls or sent the character into a completely random direction.
*I did get it working but in a ugly and wrong way. I had the charater move forward until it hit and wall. Then it turned right and kept moving until it could turn left and continue towards the destination. This works but i dont think people want their teams monsters running around on walls
Edit:
Code below is now working! I found that for some reason the points were backwards so i had to invert the Point list. No all i need to do is interpolate between points to give smooth movement. However, I do ask is there any way i cant add more bias towards walls. For example making it so the point never goes within 1 unit of a wall?
package NavMesh;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import toolbox.Maths;
public class MovementPath {
private Node[][] mapOriginal;
private Node[][] mapPath;
public boolean solving = true;
public int startX, startY, finishX, finishY, cells;
private int checks = 0;
private int length = 0;
int realStartX, realStartY, realFinishX, realFinishY;
NavMesh mesh;
private Algorithm alg;
List<Point> path = new ArrayList<Point>();
public MovementPath(NavMesh mesh,int startX, int startY, int finishX, int finishY) {
this.mapOriginal = mesh.getMapCopy();
this.mesh = mesh;
this.startX = startX;
this.startY = startY;
this.finishX = finishX;
this.finishY = finishY;
this.cells = mapOriginal.length;
realStartX = startX;
realStartY = startY;
realFinishX = finishX;
realFinishY = finishY;
this.startX = (int) (Math.floor((float) startX / (float) mesh.cellWidth));
this.startY = (int) (Math.floor((float) startY / (float) mesh.cellHeight));
this.finishX = (int) (Math.floor((float) finishX / (float) mesh.cellWidth));
this.finishY = (int) (Math.floor((float) finishY / (float) mesh.cellHeight));
mapPath = new Node[mapOriginal.length][mapOriginal.length];
System.arraycopy(mapOriginal, 0, mapPath, 0, mapOriginal.length);
mapPath[this.startX][this.startY] = new Node(0,this.startX,this.startY);;
mapPath[this.finishX][this.finishY] = new Node(1,this.finishX,this.finishY);
addPointCentered(realFinishX,realFinishY);
alg = new Algorithm();
//alg.AStar();
alg.Dijkstra();
addPointCentered(realStartX,realStartY);
mesh.drawMap(Integer.toString(Maths.randomRange(0, 1000)), mapPath);
}
public Path getPath(){
//System.out.println("Returning path with " + getPathPoints().size() + " points");
return new Path(getPathPoints());
}
private void addPointCentered(int x, int y) {
path.add(new Point(x+(mesh.cellWidth/2),y+(mesh.cellHeight/2)));
}
public List<Point> getPathPoints(){
List<Point> rPath = new ArrayList<Point>();
for(int i = path.size()-1; i >= 0; i--) {
rPath.add(path.get(i));
}
return rPath;
}
class Algorithm { //ALGORITHM CLASS
//A STAR WORKS ESSENTIALLY THE SAME AS DIJKSTRA CREATING A PRIORITY QUE AND PROPAGATING OUTWARDS UNTIL IT FINDS THE END
//HOWEVER ASTAR BUILDS IN A HEURISTIC OF DISTANCE FROM ANY NODE TO THE FINISH
//THIS MEANS THAT NODES THAT ARE CLOSER TO THE FINISH WILL BE EXPLORED FIRST
//THIS HEURISTIC IS BUILT IN BY SORTING THE QUE ACCORDING TO HOPS PLUS DISTANCE UNTIL THE FINISH
public void AStar() {
ArrayList<Node> priority = new ArrayList<Node>();
priority.add(mapPath[startX][startY]);
while(solving) {
if(priority.size() <= 0) {
solving = false;
break;
}
int hops = priority.get(0).getHops()+1;
ArrayList<Node> explored = exploreNeighbors(priority.get(0),hops);
if(explored.size() > 0) {
priority.remove(0);
priority.addAll(explored);
} else {
priority.remove(0);
}
sortQue(priority); //SORT THE PRIORITY QUE
}
}
public void Dijkstra() {
ArrayList<Node> priority = new ArrayList<Node>(); //CREATE A PRIORITY QUE
priority.add(mapPath[startX][startY]); //ADD THE START TO THE QUE
while(solving) {
if(priority.size() <= 0) { //IF THE QUE IS 0 THEN NO PATH CAN BE FOUND
solving = false;
break;
}
int hops = priority.get(0).getHops()+1; //INCREMENT THE HOPS VARIABLE
ArrayList<Node> explored = exploreNeighbors(priority.get(0), hops); //CREATE AN ARRAYLIST OF NODES THAT WERE EXPLORED
if(explored.size() > 0) {
priority.remove(0); //REMOVE THE NODE FROM THE QUE
priority.addAll(explored); //ADD ALL THE NEW NODES TO THE QUE
} else { //IF NO NODES WERE EXPLORED THEN JUST REMOVE THE NODE FROM THE QUE
priority.remove(0);
}
}
}
public ArrayList<Node> sortQue(ArrayList<Node> sort) { //SORT PRIORITY QUE
int c = 0;
while(c < sort.size()) {
int sm = c;
for(int i = c+1; i < sort.size(); i++) {
if(sort.get(i).getEuclidDist(finishX,finishY)+sort.get(i).getHops() < sort.get(sm).getEuclidDist(finishX,finishY)+sort.get(sm).getHops())
sm = i;
}
if(c != sm) {
Node temp = sort.get(c);
sort.set(c, sort.get(sm));
sort.set(sm, temp);
}
c++;
}
return sort;
}
/*
public ArrayList<Node> exploreNeighbors(Node current, int hops) { //EXPLORE NEIGHBORS
ArrayList<Node> explored = new ArrayList<Node>(); //LIST OF NODES THAT HAVE BEEN EXPLORED
for(int a = -1; a <= 1; a++) {
for(int b = -1; b <= 1; b++) {
int xbound = current.getX()+a;
int ybound = current.getY()+b;
if((xbound > -1 && xbound < cells) && (ybound > -1 && ybound < cells)) { //MAKES SURE THE NODE IS NOT OUTSIDE THE GRID
Node neighbor = mapPath[xbound][ybound];
if((neighbor.getHops()==-1 || neighbor.getHops() > hops) && neighbor.getType()!=2) { //CHECKS IF THE NODE IS NOT A WALL AND THAT IT HAS NOT BEEN EXPLORED
explore(neighbor, current.getX(), current.getY(), hops); //EXPLORE THE NODE
explored.add(neighbor); //ADD THE NODE TO THE LIST
}
}
}
}
return explored;
}
*/
public ArrayList<Node> exploreNeighbors(Node current, int hops) { //EXPLORE NEIGHBORS
ArrayList<Node> explored = new ArrayList<Node>(); //LIST OF NODES THAT HAVE BEEN EXPLORED
//test(hops, current, explored,current.getX(),current.getY());
//test(hops, current, explored,current.getX()+1,current.getY());
//test(hops, current, explored,current.getX()-1,current.getY());
//test(hops, current, explored,current.getX(),current.getY()+1);
//test(hops, current, explored,current.getX(),current.getY()-1);
for(int a = -1; a <= 1; a++) {
for(int b = -1; b <= 1; b++) {
test(hops, current, explored,current.getX()+a,current.getY()+b);
}
}
return explored;
}
private void test(int hops, Node current, ArrayList<Node> explored, int xbound, int ybound) {
if((xbound > -1 && xbound < cells) && (ybound > -1 && ybound < cells)) { //MAKES SURE THE NODE IS NOT OUTSIDE THE GRID
Node neighbor = mapPath[xbound][ybound];
if((neighbor.getHops()==-1 || neighbor.getHops() > hops) && neighbor.getType()!=2) { //CHECKS IF THE NODE IS NOT A WALL AND THAT IT HAS NOT BEEN EXPLORED
explore(neighbor, current.getX(), current.getY(), hops); //EXPLORE THE NODE
explored.add(neighbor); //ADD THE NODE TO THE LIST
}
}
}
public void explore(Node current, int lastx, int lasty, int hops) { //EXPLORE A NODE
if(current.getType()!=0 && current.getType() != 1) //CHECK THAT THE NODE IS NOT THE START OR FINISH
current.setType(4); //SET IT TO EXPLORED
current.setLastNode(lastx, lasty); //KEEP TRACK OF THE NODE THAT THIS NODE IS EXPLORED FROM
current.setHops(hops); //SET THE HOPS FROM THE START
checks++;
if(current.getType() == 1) { //IF THE NODE IS THE FINISH THEN BACKTRACK TO GET THE PATH
backtrack(current.getLastX(), current.getLastY(),hops);
}
}
public void backtrack(int lx, int ly, int hops) { //BACKTRACK
length = hops;
while(hops > 1) { //BACKTRACK FROM THE END OF THE PATH TO THE START
Node current = mapPath[lx][ly];
current.setType(5);
addPointCentered(lx*mesh.cellWidth,ly*mesh.cellHeight);
//System.out.println("New Point: " + path.get(path.size()-1).toString());
lx = current.getLastX();
ly = current.getLastY();
hops--;
}
solving = false;
}
}
}
Try A*, I used that for a path finding problem. It is easy to implement for grid based movement and very fast. I implemented it using the pseudocode on the wikipedia page.

How to make a shuffle method in a linked list

I am trying to make a shuffle method in my LinkedList. Currently, my method of shuffling is to generate a random number, n, between 1 to 10, and take the n(th) number of card and move it to the front. Then it will loop in a random amount of time. However, my current code does not seem to work as the card it takes just get removed instead of bringing it to the front.
public void shuffle() {
Node current = head;
int randomX = (int) (Math.random() * 10 + 1);
for (int x = 0; x < randomX; x++) {
int randomY = (int) (Math.random() * 10 + 1);
for (int y = 0; y < randomY; y++) {
if (current.getNext() != null) {
current = current.getNext();
System.out.println("Yup");
System.out.println(current);
System.out.println(y);
}
else {
current = head;
System.out.println("nope");
current = current.getNext();
}
if (current.getPrevious() != null){
current.getPrevious().setNext(current.getNext());
head.setPrevious(current);
current.setPrevious(head);
}
head = current;
}
}
}
Make sure that when you find the node you are looking for that you set its previous node's next to its next AND you set the node's next previous to its previous
Node temp = head;
int randomX = (int) (Math.random() * 10 + 1);
//simply go until the randomX
while(randomX-- > 0 && temp.getNext() != null)
temp = temp.getNext();
//remove the Nth node from the list
temp.getPrevious().setNext(temp.getNext());
if(temp.getNext() != null)
temp.getNext().setPrevious(temp.getPrevious());
//set it to point to the head
temp.setNext(head);
temp.setPrevious(null);
//now set the Head to the Nth node we found
head = temp;
It look like your move the randomly chosen node to head is misplaced. It should be outside the loop that chooses the one to move.
A few comments would have made this obvious.
public void shuffle() {
Node current = head;
// How many times to shuffle.
int randomX = (int) (Math.random() * 10 + 1);
// Move random node to head random number of times.
for (int x = 0; x < randomX; x++) {
// Pick the one to move.
int randomY = (int) (Math.random() * 10 + 1);
// Go find it.
for (int y = 0; y < randomY; y++) {
if (current.getNext() != null) {
current = current.getNext();
System.out.println("Yup");
System.out.println(current);
System.out.println(y);
} else {
// Hit end of list - go back to start.
current = head;
System.out.println("nope");
current = current.getNext();
}
}
// Bring the chosen one to `head` - **** I moved this OUTSIDE the loop above.
if (current.getPrevious() != null) {
current.getPrevious().setNext(current.getNext());
head.setPrevious(current);
current.setPrevious(head);
}
head = current;
}
}

Algorithm for finding all paths in a NxN grid

Imagine a robot sitting on the upper left hand corner of an NxN grid. The robot can only move in two directions: right and down. How many possible paths are there for the robot?
I could find solution to this problem on Google, but I am not very clear with the explanations. I am trying to clearly understand the logic on how to solve this and implement in Java. Any help is appreciated.
Update: This is an interview question. For now, I am trying to reach the bottom-right end and print the possible paths.
public static int computePaths(int n){
return recursive(n, 1, 1);
}
public static int recursive(int n, int i, int j){
if( i == n || j == n){
//reach either border, only one path
return 1;
}
return recursive(n, i + 1, j) + recursive(n, i, j + 1);
}
To find all possible paths:
still using a recursive method. A path variable is assigned "" in the beginning, then add each point visited to 'path'. A possible path is formed when reaching the (n,n) point, then add it to the list.
Each path is denoted as a string, such as " (1,1) (2,1) (3,1) (4,1) (4,2) (4,3) (4,4)". All possible paths are stored in a string list.
public static List<String> robotPaths(int n){
List<String> pathList = new ArrayList<String>();
getPaths(n, 1,1, "", pathList);
return pathList;
}
public static void getPaths(int n, int i, int j, String path, List<String> pathList){
path += String.format(" (%d,%d)", i , j);
if( i ==n && j == n){ //reach the (n,n) point
pathList.add(path);
}else if( i > n || j > n){//wrong way
return;
}else {
getPaths(n, i +1, j , path, pathList);
getPaths(n, i , j +1, path, pathList);
}
}
I see no indications for obstacles in your question so we can assume there are none.
Note that for an n+1 by n+1 grid, a robot needs to take exactly 2n steps in order to reach the lower right corner. Thus, it cannot make any more than 2n moves.
Let's start with a simpler case: [find all paths to the right down corner]
The robot can make exactly choose(n,2n)= (2n)!/(n!*n!) paths: It only needs to choose which of the 2n moves will be right, with the rest being down (there are exactly n of these).
To generate the possible paths: just generate all binary vectors of size 2n with exactly n 1's. The 1's indicate right moves, the 0's, down moves.
Now, let's expand it to all paths:
First choose the length of the path. To do so, iterate over all possibilities: 0 <= i <= 2n, where i is the length of the path. In this path there are max(0,i-n) <= j <= min(i,n) right steps.
To generate all possibilities, implement the following pseudo-code:
for each i in [0,2n]:
for each j in [max(0,i-n),min(i,n)]:
print all binary vectors of size i with exactly j bits set to 1
Note 1: printing all binary vectors of size i with j bits set to 1 could be computationally expensive. That is expected since there are an exponential number of solutions.
Note 2: For the case i=2n, you get j in [n,n], as expected (the simpler case described above).
https://math.stackexchange.com/questions/104032/finding-points-in-a-grid-with-exactly-k-paths-to-them - look here at my solution. Seems that it is exactly what you need (yes, statements are slightly different, but in general case they are just the same).
This is for if the robot can go 4 directions rather than just 2, but the recursive solution below (in Javascript) works and I've tried to make it as legible as possible:
//first make a function to create the board as an array of arrays
var makeBoard = function(n) {
var board = [];
for (var i = 0; i < n; i++) {
board.push([]);
for (var j = 0; j < n; j++) {
board[i].push(false);
}
}
board.togglePiece = function(i, j) {
this[i][j] = !this[i][j];
}
board.hasBeenVisited = function(i, j) {
return !!this[i][j];
}
board.exists = function(i, j) {
return i < n && i > -1 && j < n && j > -1;
}
board.viablePosition = function(i, j) {
return board.exists(i, j) && !board.hasBeenVisited(i,j);
}
return board;
};
var robotPaths = function(n) {
var numPaths = 0;
//call our recursive function (defined below) with a blank board of nxn, with the starting position as (0, 0)
traversePaths(makeBoard(n), 0, 0);
//define the recursive function we'll use
function traversePaths(board, i, j) {
//BASE CASE: if reached (n - 1, n - 1), count as solution and stop doing work
if (i === (n - 1) && j === (n - 1)) {
numPaths++;
return;
}
//mark the current position as having been visited. Doing this after the check for BASE CASE because you don't want to turn the target position (i.e. when you've found a solution) to true or else future paths will see it as an unviable position
board.togglePiece(i, j);
//RECURSIVE CASE: if next point is a viable position, go there and make the same decision
//go right if possible
if (board.viablePosition(i, j + 1)) {
traversePaths(board, i, j + 1);
}
//go left if possible
if (board.viablePosition(i, j - 1)) {
traversePaths(board, i, j - 1);
}
//go down if possible
if (board.viablePosition(i + 1, j)) {
traversePaths(board, i + 1, j);
}
//go up if possible
if (board.viablePosition(i - 1, j)) {
traversePaths(board, i - 1, j);
}
//reset the board back to the way you found it after you've gone forward so that other paths can see it as a viable position for their routes
board.togglePiece(i, j);
}
return numPaths;
};
A cleaner version:
var robotPaths = function(n, board, i, j) {
board = board || makeBoard(n),
i = i || 0,
j = j || 0;
// If current cell has been visited on this path or doesn't exist, can't go there, so do nothing (no need to return since there are no more recursive calls below this)
if (!board.viablePosition(i, j)) return 0;
// If reached the end, add to numPaths and stop recursing
if (i === (n - 1) && j === (n - 1)) return 1;
// Mark current cell as having been visited for this path
board.togglePiece(i, j);
// Check each of the four possible directions
var numPaths = robotPaths(n, board, i + 1, j) + robotPaths(n, board, i - 1, j) + robotPaths(n, board, i, j + 1) + robotPaths(n, board, i, j - 1);
// Reset current cell so other paths can go there (since board is a pointer to an array that every path is accessing)
board.togglePiece(i, j);
return numPaths;
}
So:
robotPaths(5); //returns 8512
Scenario:
1. Imagine there is NxN zero indexed matrix.
2. Initial position of robot is upper-left corner i.e. (N-1, N-1)
3. Robot wants to reach lower right corner i.e. at (0,0)
Solution:
-- In any possible solution robot will move N rights steps and N down steps to reach (0,0), or we can say that initial robot has permission to move N rights steps and N down steps.
-- When ever robot moves right we reduce its remaining number of right steps by 1, same is for down movement.
-- At every position(except at boundary, where it will have only one option) robot have two options, one is it can go down or other is it can go right.
-- It will terminate when robot will have no remaining down of right steps.
**Below code also have driver method main(), you can change the value of N. N can be >=1
public class RobotPaths {
public static int robotPaths(int down, int right, String path)
{
path = path+ down +","+ right +" ";
if(down==0 && right==0)
{
System.out.println(path);
return 1;
}
int counter = 0;
if(down==0)
counter = robotPaths(down, right-1, path);
else if(right==0)
counter = robotPaths(down-1, right, path);
else
counter = robotPaths(down, right-1, path) + robotPaths(down-1, right, path);
return counter;
}
public static void main(String[] args)
{
int N = 1;
System.out.println("Total possible paths: "+RobotPaths.robotPaths(N-1, N-1, ""));
}
}
If you just need a count of the valid paths:
Let's say you have a matrix n*m matrix and you set all cells to zero and the "offlimit" cells to -1.
You can then solve the problem with dynamic programming:
// a is a matrix with 0s and -1s
// n, m are the dimensions
// M is 10^9-7 incase you have a large matrix
if (a[0][0] == 0) a[0][0] = 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (a[i][j] == -1) continue;
if (i > 0) a[i][j] = (a[i][j] + max(a[i-1][j], 0LL)) % M;
if (j > 0) a[i][j] = (a[i][j] + max(a[i][j-1], 0LL)) % M;
}
}
// answer at lower right corner
cout << a[n-1][m-1];
Blazing fast without recursion or bloaty data structures.
NOTE: this was deleted due to being duplicate but since this is the best thread on this topic, I've deleted my answer from elsewhere and will add this here.
Here is c# version (just for reference) to find unique paths (note here is the version which returns number of paths using dynamic programming (memorization - lazy) - Calculating number of moves from top left corner to bottom right with move in any direction) (you may refer to my blog for more details: http://codingworkout.blogspot.com/2014/08/robot-in-grid-unique-paths.html)
Tuple<int, int>[][] GetUniquePaths(int N)
{
var r = this.GetUniquePaths(1, 1, N);
return r;
}
private Tuple<int, int>[][] GetUniquePaths(int row, int column, int N)
{
if ((row == N) && (column == N))
{
var r = new Tuple<int, int>[1][];
r[0] = new Tuple<int, int>[] { new Tuple<int,int>(row, column) };
return r;
}
if ((row > N) || (column > N))
{
return new Tuple<int, int>[0][];
}
var uniquePathsByMovingDown = this.GetUniquePaths(row + 1, column, N);
var uniquePathsByMovingRight = this.GetUniquePaths(row, column + 1, N);
List<Tuple<int, int>[]> paths = this.MergePaths(uniquePathsByMovingDown,
row, column).ToList();
paths.AddRange(this.MergePaths(uniquePathsByMovingRight, row, column));
return paths.ToArray();
}
where
private Tuple<int, int>[][] MergePaths(Tuple<int, int>[][] paths,
int row, int column)
{
Tuple<int, int>[][] mergedPaths = new Tuple<int, int>[paths.Length][];
if (paths.Length > 0)
{
Assert.IsTrue(paths.All(p => p.Length > 0));
for (int i = 0; i < paths.Length; i++)
{
List<Tuple<int, int>> mergedPath = new List<Tuple<int, int>>();
mergedPath.Add(new Tuple<int, int>(row, column));
mergedPath.AddRange(paths[i]);
mergedPaths[i] = mergedPath.ToArray();
}
}
return mergedPaths;
}
Unit Tests
[TestCategory(Constants.DynamicProgramming)]
public void RobotInGridTests()
{
int p = this.GetNumberOfUniquePaths(3);
Assert.AreEqual(p, 6);
int p1 = this.GetUniquePaths_DP_Memoization_Lazy(3);
Assert.AreEqual(p, p1);
var p2 = this.GetUniquePaths(3);
Assert.AreEqual(p1, p2.Length);
foreach (var path in p2)
{
Debug.WriteLine("===================================================================");
foreach (Tuple<int, int> t in path)
{
Debug.Write(string.Format("({0}, {1}), ", t.Item1, t.Item2));
}
}
p = this.GetNumberOfUniquePaths(4);
Assert.AreEqual(p, 20);
p1 = this.GetUniquePaths_DP_Memoization_Lazy(4);
Assert.AreEqual(p, p1);
p2 = this.GetUniquePaths(4);
Assert.AreEqual(p1, p2.Length);
foreach (var path in p2)
{
Debug.WriteLine("===================================================================");
foreach (Tuple<int, int> t in path)
{
Debug.Write(string.Format("({0}, {1}), ", t.Item1, t.Item2));
}
}
}
Here is a full implementation that works for both rectangular and square grids. I will leave you to figure out how to take care of the excess "=>" at the end of each path.
import java.util.Arraylist;
public class PrintPath
{
static ArrayList<String> paths = new ArrayList<String>();
public static long getUnique(int m, int n, int i, int j, String pathlist)
{
pathlist += ("(" + i + ", " + (j) + ") => ");
if(m == i && n == j)
{
paths.add(pathlist);
}
if( i > m || j > n)
{
return 0;
}
return getUnique(m, n, i+1, j, pathlist)+getUnique(m, n, i, j+1, pathlist);
}
public static void printPaths()
{
int count = 1;
System.out.println("There are "+paths.size() + " unique paths: \n");
for (int i = paths.size()-1; i>=0; i--)
{
System.out.println( "path " + count + ": " + paths.get(i));
count++;
}
}
public static void main(String args[])
{
final int start_Point = 1;
int grid_Height = 2;
int grid_Width = 2;
getUnique(grid_Height, grid_Width, start_Point, start_Point, "");
printPaths();
}
}
Below is the code in Java to count all the possible paths from top left corner to bottom right corner of a NXN matrix.
public class paths_in_matrix {
/**
* #param args
*/
static int n=5;
private boolean[][] board=new boolean[n][n];
int numPaths=0;
paths_in_matrix(){
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
board[i][j]=false;
}
}
}
private void togglePiece(int i,int j){
this.board[i][j]=!this.board[i][j];
}
private boolean hasBeenVisited(int i,int j){
return this.board[i][j];
}
private boolean exists(int i,int j){
return i < n && i > -1 && j < n && j > -1;
}
private boolean viablePosition(int i,int j){
return exists(i, j) && !hasBeenVisited(i,j);
}
private void traversePaths(int i,int j){
//BASE CASE: if reached (n - 1, n - 1), count as path and stop.
if (i == (n - 1) && j == (n - 1)) {
this.numPaths++;
return;
}
this.togglePiece(i, j);
//RECURSIVE CASE: if next point is a viable position, go there and make the same decision
//go right if possible
if (this.viablePosition(i, j + 1)) {
traversePaths(i, j + 1);
}
//go left if possible
if (this.viablePosition(i, j - 1)) {
traversePaths( i, j - 1);
}
//go down if possible
if (this.viablePosition(i + 1, j)) {
traversePaths( i + 1, j);
}
//go up if possible
if (this.viablePosition(i - 1, j)) {
traversePaths(i - 1, j);
}
//reset the board back to the way you found it after you've gone forward so that other paths can see it as a viable position for their routes
this.togglePiece(i, j);
}
private int robotPaths(){
traversePaths(0,0);
return this.numPaths;
}
public static void main(String[] args) {
paths_in_matrix mat=new paths_in_matrix();
System.out.println(mat.robotPaths());
}
}
Here you go (python):
def numPathsFromULtoRD(m,n):
return factorial(m+n-2)//(factorial(m-1)*factorial(n-1))
def solution(m,n):
result = 0
for i in range(m):
for j in range(n):
if i == 0 and j == 0:
continue
result += numPathsFromULtoRD(i+1,j+1)
return result
int N;
function num_paths(intx,int y)
{
int[][] arr = new int[N][N];
arr[N-1][N-1] = 0;
for(int i =0;i<N;i++)
{
arr[N-1][i]=1;
arr[i][N-1]=1;
}
for(int i = N-2;i>=0;i--)
{
for(int j=N-2;j>=0;j--)
{
arr[i][j]= arr[i+1][j]+arr[i][j+1];
}
}
return arr[0][0];
}

Categories