The goal of this BFS is to find a solution to a 3x2 puzzle game(0 is blank space and you can only move pieces to that space)
start:
1 4 2
5 3 0
Goal:
0 1 2
3 4 5
The problem is that my queue becomes empty before a solution is found, how is that possible? One of the paths in the search tree must return a solution here. Please let me know if I can clarify anything.
Node Class (represents a state of the game):
mport java.lang.reflect.Array;
import java.util.*;
public class Node {
public int[] state = new int[6];
private Node parent;
public Node(int[] initialState, Node parent){
this.parent = parent;
this.state = initialState;
}
public boolean isGoal(){
int[] goal = {0,1,2,3,4,5};
return Arrays.equals(state, goal);
}
public ArrayList<Node> getChildren(){
ArrayList<Node> children = new ArrayList<>();
Integer[] newInt = new Integer[getState().length];
for (int i = 0; i < getState().length; i++) {
newInt[i] = Integer.valueOf(getState()[i]);
}
int position = Arrays.asList(newInt).indexOf(0);
switch(position){
case 0:
children.add(right());
children.add(down());
break;
case 1:
children.add(down());
children.add(left());
children.add(right());
break;
case 2:
children.add(down());
children.add(left());
break;
case 3:
children.add(up());
children.add(right());
break;
case 4:
children.add(up());
children.add(left());
children.add(right());
break;
case 5:
children.add(up());
children.add(left());
break;
}
return children;
}
public int[] getState(){
return this.state;
}
public int getBlankIndex() {
for (int i = 0; i < state.length; i++)
if (state[i] == 0) return i;
return -1;
}
public Node up(){
int[] newer = state.clone();
int blankIndex = getBlankIndex();
int temp = newer[blankIndex - 3];
newer[blankIndex] = temp;
newer[blankIndex - 3] = 0;
return new Node(newer, this);
}
public Node down(){
int[] newer = state.clone();
int blankIndex = getBlankIndex();
int temp = newer[blankIndex + 3];
newer[blankIndex] = temp;
newer[blankIndex + 3] = 0;
return new Node(newer, this);
}
public Node left(){
int[] newer = state.clone();
int blankIndex = getBlankIndex();
int temp = newer[blankIndex - 1];
newer[blankIndex] = temp;
newer[blankIndex - 1] = 0;
return new Node(newer, this);
}
public Node right(){
int[] newer = state.clone();
int blankIndex = getBlankIndex();
int temp = newer[blankIndex + 1];
newer[blankIndex] = temp;
newer[blankIndex + 1] = 0;
return new Node(newer, this);
}
public void print(){
System.out.println("---------");
System.out.println(Arrays.toString(Arrays.copyOfRange(getState(), 0, 3)));
System.out.println(Arrays.toString(Arrays.copyOfRange(getState(), 3, 6)));
System.out.println("---------");
}
public void printTrace(){
Stack<Node> stack = new Stack<>();
Node current = this;
while (current.parent != null){
stack.push(current);
current = current.parent;
}
while (!stack.isEmpty()){
stack.pop().print();
}
}
#Override
public boolean equals(Object object){
if (object instanceof Node) {
Node node2 = (Node) object;
return (Arrays.equals(node2.getState(), this.getState()));
}
return false;
}
#Override
public int hashCode() {
return this.hashCode();
}
}
Driver Class:
import java.util.*;
public class Driver {
public static void main(String[] args){
Node test = new Node(new int[]{1, 4, 2, 5, 3, 0}, null);
BFS(test);
System.out.println("done");
}
public static void BFS(Node initial){
Queue<Node> queue = new LinkedList<>();
ArrayList<Node> explored = new ArrayList<>();
queue.add(initial);
Node current = initial;
while (!queue.isEmpty() && !current.isGoal()){
current = queue.remove();
for (Node child: current.getChildren()){
if (!explored.contains(child)) {
queue.add(child);
explored.add(current);
}
}
}
System.out.println("DONEDONEDONE");
current.printTrace();
}
}
This is a very surprising problem!
I haven't looked at the code yet, it seemed more or less ok.
I'll instead address the question:
The problem is that my queue becomes empty before a solution is found, how is that possible?
The code is not the problem.
The problem is that your puzzle is unsolvable.
The funny thing is that
parity(permutation) * (-1)^{manhattanMetric(positionOfZeroTile)}
is an invariant that is preserved during the entire game.
Let me briefly explain what it means.
(It's essentially the same argument as here: https://en.wikipedia.org/wiki/15_puzzle )
The parity of a permutation is (-1)^{numberOfTranspositions}.
The number of transpositions is essentially just the number of swaps that
the bubble-sort would need to sort the sequence.
The manhattan metric of the zero-tile position is x-coordinate of the zero-tile
added with the y-coordinate of the zero-tile.
Each time you swap a tile with zero, the parity of the permutation changes
the sign.
At the same time, the manhattan metric between the upper left corner and
the position of the zero-tile changes by +1 or -1. In both cases,
(-1)^{manhattanDist} also changes the sign.
Thus, the product of the parity and (-1)^{manhattanDist} is constant.
If you now look at the solved game
0 1 2
3 4 5
then the number of transpositions is 0, parity is 1, the manhattan distance is 0.
Thus, the invariant is (+1).
However, if you look at this:
1 4 2
5 3 0
then you can calculate that the number of transpositions is even (bubble-sort it!),
parity is (+1), and the manhattan distance is 2 + 1 = 3, and thus uneven.
Thus, the invariant is (+1) * (-1)^3 = (-1).
But (-1) is not (+1). Therefore, your game is unsolvable in principle, no matter
how good your BFS is.
Another (more intuitive but less rigorous) way to see quickly that your puzzle is "broken"
is to swap two non-zero tiles in the beginning.
1 4 2
3 5
This is almost immediately solvable:
1 4 2 1 2 1 2
3 5 3 4 5 3 4 5
So, if you don't want to waste any time searching for bugs that aren't there,
don't skip the Group Theory lectures next time ;)
An error I can find is that you only add current to the explored list if it doesn‘t contain child. Additionally, you do this within the loop through the children, so it might also be that you add it multiple times. (Though, this shouldn‘t affect your result)
Related
My end goal is to do a findKthElement function and the only way I can think of is to perform iterative inorder traversal so that I can keep a counter, which obviously doesn't work if its recursive. I have tried my best at an implementation similar to a BST but its not working, just printing the same thing infinately. Here is my attempt:
public void findKth() {
Stack<BTreeNode> s = new Stack<>();
BTreeNode current = this.root;
while(current != null || !s.isEmpty()) {
int i;
for(i = 0; i < current.numNodes; i++) {
if(!current.isLeaf) {
s.push(current);
current = current.children[i];
}
}
current = s.pop();
for(int j = 0; j < current.numNodes; j++) {
System.out.println(current.keys[j].getName());
}
}
}
keep a counter, which obviously doesn't work if its recursive
There is no problem keeping a counter in a recursive solution. You just need to make sure it's a mutable reference. For example:
public class Counter {
private int count;
public boolean complete() { return count == 0; }
public void decrement() { count--; }
}
Optional<Node> findKthChild(Node node, Counter counter) {
if (counter.isLeaf()) {
if (counter.complete())
return Optional.of(node);
counter.decrement();
} else {
for (Node child: getChildren()) {
Optional<Node> kthChild = findKthChild(child, counter);
if (kthChild.isPresent())
return kthChild;
}
}
return Optional.empty();
}
If you're familiar with streams the internal for loop could be:
return getChildren().stream()
.map(ch -> findKthChild(ch, counter))
.filter(Optional::isPresent)
.findFirst().orElse(Optional.empty());
This reeks of home work. One should try to solve it by tracing the needed steps manually, with pen and paper.
I am not claiming that the code below is correct, or good.
It is to indicate that an in-order traversal, depth first, needs to come back a some nodes ith sub-branch to continue with the next child.
For that I use the new record class as stack element, a class consisting of just BTreeNode node and int index.
public String findKth(int k) {
record NodePos(BTreeNode node, int index) {};
Stack<NodePos> stack = new Stack<>();
stack.push(new NodePos(this.root, -1);
while (!stack.isEmpty()) {
NodePos pos = stack.pop();
pos = new NodePos(pos.node, pos.index + 1);
if (pos.index >= pos.node.numNodes) { // Past end of child nodes.
continue;
}
// Sub-branch:
if (!pos.node.isLeaf) {
stack.push(new NodePos(pos.node.children[pos.index], -1);
continue;
}
// Key:
if (pos.index + 1 >= pos.node.numNodes) { // Past end of child keys.
continue;
}
System.console().printf("%d. %s%n", k, pos.node.keys[pos.index]);
if (k <= 0) {
return pos.node.keys[pos.index];
}
--k;
stack.push(pos);
}
}
There are numNodes sub-branches (node.children)and numNodes - 1 keys in a node (node.keys).
When you are at the i th sub-branch, you may first continue with the subtree, and when not sufficient (decreasing k still greater 0), then continue with the i-1 th key.
As you see, when not manually executing the code, it is hard to read it. For that it invaluable advice to work out these things yourself.
A recursive solution is easier by the way.
Okay, a working solution
My answer above was intended to think about, certainly not correct,
as the OP did not show having seriously thought about the algorithm,
given the OPs code. But there is effort evidently.
Hence a readable recursive solution. Still in a form which cannot
be given back as ones own home work.
static class BTreeNode {
int numNodes;
boolean isLeaf;
BTreeNode[] children;
int[] keys;
BTreeNode(int... keys) {
numNodes = keys.length + 1;
this.keys = keys.clone();
isLeaf = true;
}
public void addChildren(BTreeNode... children) {
assert children.length == numNodes;
this.children = children.clone();
isLeaf = false;
}
}
public static OptionalInt findKth(BTreeNode node, AtomicInteger k) {
if (node == null || k.get() < 0) {
return OptionalInt.empty();
}
for (int i = 0; i < node.numNodes; ++i) {
if (!node.isLeaf) {
OptionalInt result = findKth(node.children[i], k);
if (result.isPresent()) {
return result;
}
}
if (i + 1 < node.numNodes) {
int j = k.getAndDecrement();
System.out.printf("%d. %s%n", j, node.keys[i]);
if (j <= 0) {
return OptionalInt.of(node.keys[i]);
}
}
}
return OptionalInt.empty();
}
public static void main(String[] args) {
//
// (4 8 12)
// (1 2 3) (5 6 7) (9 10 11) (13 14 15)
BTreeNode n1to3 = new BTreeNode(1, 2, 3);
BTreeNode n5to7 = new BTreeNode(5, 6, 7);
BTreeNode n9to11 = new BTreeNode(9, 10, 11);
BTreeNode n13to15 = new BTreeNode(13, 14, 15);
BTreeNode root = new BTreeNode(4, 8, 12);
root.addChildren(n1to3, n5to7, n9to11, n13to15);
OptionalInt key5 = findKth(root, new AtomicInteger(5));
System.out.println("The result is " + key5.orElse(-1));
}
One walks in-order through the B-tree decrementing the asked k till it reaches 0. The in-order walk with numNodes subtree branches and numNodes - 1 keys requires a for+if.
The AtomicInteger is used to have a counter, a result from findKth otherwise one would need an input parameter k, and a new value for k on return. That can be done.
Optimisation: One could skip visiting a subtree, if one knew the number of elements in an entire subtree. For leaf nodes that would be numNodes.
My homework problem presents some courses and how many depend on each other. For an instance, the first test (courses,depedent on): (1,3) (2,3) (4,1) (4,2) and we identify that there are 5 courses and 4 dependent on each other (Thats why 5 is not on the list, its just 0)
I know from a topological search, that the following is a valid solution:
1 3 2 4 0
I then need to print the number of semesters it takes to take these courses and I know it is 3 semester, due to the relations between them. We first have to take course 1 and 2 to take 3 and since we already have 1 2, we can take course 4.
So I need help figuring some code out that does this. That's where I need you guys help
I've tried to simply count the courses that are connected, but failed. I've tried to think of something that I can do but literally nothing pops up as a solution.
The graph class:
public class Graph {
int V;
LinkedList<Integer> adjList[];
public Graph(int vertex) {
this.V = vertex;
//We then define the num of vertexes in the adjlist
adjList = new LinkedList[vertex];
//Then create a new list for each vertex so we can create a link between the vertexes
for (int i = 0; i < vertex; i++) {
adjList[i] = new LinkedList<>();
}
}
//Directed graph
public void addEdge(int source, int destination) {
//Add the edge from the source node to the destination node
adjList[source].add(destination);
adjList[destination].add(source);
}
//Method to print the graph if necessary
public void printGraph(Graph graph) {
for (int i = 0; i < graph.V; i++) {
System.out.println("Adjacency list over vertex: " + i);
System.out.print("head");
for (Integer treeCrawler : graph.adjList[i]) {
System.out.print("-> " + treeCrawler);
}
System.out.println("\n");
}
}
public LinkedList<Integer>[] getAdjList() {
return adjList;
}
}
and the topological sort class, the algorithm we are using for the problem
public class TopologicalSort {
int vertex;
//This function helps the topological function recursively by marking the vertices and pushing them onto the stack
public void topologicalHelper(int vertex, boolean marked[], Stack nodes, Graph graph) {
List<Integer>[] list = graph.getAdjList();
marked[vertex] = true;
Iterator<Integer> iterator = list[vertex].iterator();
while (iterator.hasNext()) {
int temp = iterator.next();
if (!marked[temp] && list[temp].size() != 0) {
topologicalHelper(temp, marked, nodes, graph);
}
}
nodes.add(vertex);
}
public TopologicalSort(Graph graph, int vertecies) {
vertex = vertecies;
Stack nodes = new Stack();
boolean[] marked = new boolean[vertex];
for (int i = 0; i < vertex; i++) {
if (marked[i] == false) {
topologicalHelper(i, marked, nodes, graph);
}
}
while(!nodes.empty()) {
System.out.print(nodes.pop() + " ");
}
}
}
The result should be 3, but I haven't produced that number in all my solution ideas, I need some help or hints.
Oh and the following is the console output
Adjacency list over vertex: 0
head
Adjacency list over vertex: 1
head-> 3-> 4
Adjacency list over vertex: 2
head-> 3-> 4
Adjacency list over vertex: 3
head-> 1-> 2
Adjacency list over vertex: 4
head-> 1-> 2
1 3 2 4 0
Dependency is a directed property so you should be using a directed graph. After populating the graph u will end up with a disconnected graph which has one or more trees in it. Find out which nodes are roots of each tree and use DFS to get the max depth of each tree. Assuming there is no limit on no of courses for each semester the max depth of all trees is the solution.
public class Graph {
int V;
ArrayList<Integer> adjList[];
boolean[] notRoot;
public Graph(int vertex) {
this.V = vertex;
adjList = new ArrayList[vertex];
notRoot = new boolean[vertex];
for (int i = 0; i < vertex; i++) {
adjList[i] = new ArrayList<Integer>();
}
}
public void addEdge(int a, int b) {
//asuming b is dependent on a
adjList[b].add(a);
notRoot[a]=true;
}
int maxDepthDfs(int root){
int depth=1;
for(int i=0;i<adjList[root].size();i++){
int child=adjList[root].get(i);
depth=Math.max(maxDepthDfs(child)+1,depth);
}
return depth;
}
public int getSolution(){
int ans=0;
for(int i=0;i<V;i++){
if(!notRoot[i])
ans=Math.max(ans,maxDepthDfs(i));
}
return ans;
}
}
A topological sort is simply DFS with adding nodes into a stack,(all children of a node are added first and then root is added). In Kahn's algorithm first the root elements(nodes without parent) are found and the method is called only or those nodes.
int maxDepthDfs(int root){
//since we are only calling this function for root nodes we need not check if nodes were previously visited
int depth=1;
for(int i=0;i<adjList[root].size();i++){
int child=adjList[root].get(i);
depth=Math.max(maxDepthDfs(child)+1,depth);
}
s.push(root);
return depth;
}
public int getSolution(){
s=new Stack<Integer>();
int ans=0;
for(int i=0;i<V;i++){
if(!notRoot[i])
ans=Math.max(ans,maxDepthDfs(i));
}
//stack s contains result of topological sort;
return ans;
}
I am trying to write a binary search algorithm that searches and inserts into an array here is the code. What I did is the right moves 2 times the index and the left is 1. here is the code. I was also wondering if the search method is faster than a iterative loop that goes through the array one by one?
public class BinaryTree {
int root =0;
int right = 2;
int left = 1;
int arr[];
public void search(int arr[], int value){
if(arr[right] == value){
System.out.println("found");
return;
}
if(arr[left] == value){
System.out.println("found");
return;
}
else{
left+=1;
right+=2;
}
}
public void insert(int value, int arr[]) {
this.arr = arr;
if(arr[0]==0){
arr[0] = value;
root = arr[0];
System.out.println(root);
}
if(value>root){
if(arr[right]==0){
arr[right] = value;
right+=2;
}
}
if(value<root){
if(arr[left]==0){
arr[left] = value;
left+=1;
}else{
left+=1;
}
}
}
public void printint(){
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]);
}
}
public static void main(String args[]) {
int tol[] = new int[9];
BinaryTree tree = new BinaryTree();
tree.insert(4, tol);
tree.insert(9,tol);
tree.insert(9, tol);
tree.insert(2, tol);
tree.search(tol, 9);
tree.printint();
}
}
is this considered a Binary search tree?
I think there is a specific term for what you are trying to do. The way you've currently implemented it, it will fail to insert when arr[left] or arr[right] is not 0. You need to use some type of while loop to retry after you've incremented the indices.
The subsequent insert will work because you just incremented the left/right value, but it you are incrementing the values by the wrong amount and you'll start overwriting values. You would need to increment to (index * 2) + 1 for left and (index * 2) + 2 for right.
The search would be faster in proportion to how "balanced" the tree is. A totally unbalanced tree would not be faster, and a balanced tree would be ln(n) (I think).
left *= 2;
left += 1;
right *= 2;
right += 2;
index depth element
0 0 ROOT
1 1 L1
2 1 R1
3 2 L1L2
4 2 L1R2
5 2 R1L2
6 2 R1R2
7 3 L1L2L3
8 3 L1L2R3
9 3 L1R2L3
10 3 L1R2R3
11 3 R1L2L3
12 3 R1L2R3
13 3 R1R2L3
14 3 R1R2R3
In Prim's algorithm, it is recommended to maintain the invariant in the following way :
When a vertice v is added to the MST:
For each edge (v,w) in the unexplored tree:
1. Delete w from the min heap.
2. Recompute the key[w] (i.e. it's value from the unexplored tree
to the explored one).
3. Add the value back to the heap.
So, basically this involves deletion from the heap (and heapify which takes O(logn)) and then reinserting (again O(logn))
Instead, if I use the following approach:
For each edge (v,w) in the unexplored tree:
1. Get the position of the node in the heap(array) using HashMap -> O(1)
2. Update the value in place.
3. Bubble up or bubble down accordingly. -> O(logn)
Which gives better constants than the previous one.
The controversial part is the 3rd part where Im supposed to bubble up or down.
My implementation is as follows :
public int heapifyAt(int index){
// Bubble up
if(heap[index].edgeCost < heap[(int)Math.floor(index/2)].edgeCost){
while(heap[index].edgeCost < heap[(int)Math.floor(index/2)].edgeCost){
swap(index, (int)Math.floor(index/2));
index = (int)Math.floor(index/2);
}
}else{
// Bubble down
while(index*2 + 2 < size && (heap[index].edgeCost > heap[index*2 + 1].edgeCost|| heap[index].edgeCost > heap[index*2 + 2].edgeCost)){
if(heap[index*2 + 1].edgeCost < heap[index*2 + 2].edgeCost){
//swap with left child
swap(index, index*2 + 1);
index = index*2 + 1;
}else{
//swap with right child
swap(index, index*2 + 2);
index = index*2 + 2;
}
}
}
return index;
}
And I'am plucking from the heap this way :
public AdjNode pluck(){
AdjNode min = heap[0];
int minNodeNumber = heap[0].nodeNumber;
AdjNode toRet = new AdjNode(min.nodeNumber, min.edgeCost);
heap[0].edgeCost = INF; // set this to infinity, so it'll be at the bottom
// of the heap.
heapifyat(0);
visited.add(minNodeNumber);
updatevertices(minNodeNumber); // Update the adjacent vertices
return toRet;
}
And updating the plucked vertices this way :
public void updatevertices(int pluckedNode){
for(AdjNode adjacentNode : g.list[pluckedNode]){
if(!visited.contains(adjacentNode.nodeNumber)){ // Skip the nodes that are already visited
int positionInHeap = map.get(adjacentNode.nodeNumber); // Retrive the position from HashMap
if(adjacentNode.edgeCost < heap[positionInHeap].edgeCost){
heap[positionInHeap].edgeCost = adjacentNode.edgeCost; // Update if the cost is better
heapifyAt(positionInHeap); // Now this will go bottom or up, depending on the value
}
}
}
}
But when I execute it on large graph, the code fails, There are small values in the bottom of heap and large values at the top. But the heapifyAt() API seems to work fine. So I am unable to figure out is my approach wrong or my code?
Moreover, if I replace the heapifyAt() API by siftDown(), i.e. construct the heap, it works fine, but it doesnt make sense calling siftDown() that takes O(n) time for every updates which can be processed in logarithmic time.
In short : Is it possible to update the values in Heap both way, or the algorithm is wrong, since that's why it is recommended to first remove the element from Heap and reinsert it.
EDIT : Complete code:
public class Graph1{
public static final int INF = 9999999;
public static final int NEGINF = -9999999;
static class AdjNode{
int nodeNumber;
int edgeCost;
AdjNode next;
AdjNode(int nodeNumber, int edgeCost){
this.nodeNumber = nodeNumber;
this.edgeCost = edgeCost;
}
}
static class AdjList implements Iterable<AdjNode>{
AdjNode head;
AdjList(){
}
public void add(int to, int cost){
if(head==null){
head = new AdjNode(to, cost);
}else{
AdjNode temp = head;
while(temp.next!=null){
temp = temp.next;
}
temp.next = new AdjNode(to, cost);
}
}
public Iterator<AdjNode> iterator(){
return new Iterator<AdjNode>(){
AdjNode temp = head;
public boolean hasNext(){
if(head==null){
return false;
}
return temp != null;
}
public AdjNode next(){
AdjNode ttemp = temp;
temp = temp.next;
return ttemp;
}
public void remove(){
throw new UnsupportedOperationException();
}
};
}
public void printList(){
AdjNode temp = head;
if(head==null){
System.out.println("List Empty");
return;
}
while(temp.next!=null){
System.out.print(temp.nodeNumber + "|" + temp.edgeCost + "-> ");
temp = temp.next;
}
System.out.println(temp.nodeNumber + "|" + temp.edgeCost);
}
}
static class Heap{
int size;
AdjNode[] heap;
Graph g;
int pluckSize;
Set<Integer> visited = new HashSet<Integer>();
HashMap<Integer, Integer> map = new HashMap<>();
Heap(){
}
Heap(Graph g){
this.g = g;
this.size = g.numberOfVertices;
this.pluckSize = size - 1;
heap = new AdjNode[size];
copyElements();
constructHeap();
}
public void copyElements(){
AdjList first = g.list[0];
int k = 0;
heap[k++] = new AdjNode(0, NEGINF); //First entry
for(AdjNode nodes : first){
heap[nodes.nodeNumber] = nodes;
}
for(int i=0; i<size; i++){
if(heap[i]==null){
heap[i] = new AdjNode(i, INF);
}
}
}
public void printHashMap(){
System.out.println("Priniting HashMap");
for(int i=0; i<size; i++){
System.out.println(i + " Pos in heap :" + map.get(i));
}
line();
}
public void line(){
System.out.println("*******************************************");
}
public void printHeap(){
System.out.println("Printing Heap");
for(int i=0; i<size; i++){
System.out.println(heap[i].nodeNumber + " | " + heap[i].edgeCost);
}
line();
}
public void initializeMap(){
for(int i=0; i<size; i++){
map.put(heap[i].nodeNumber, i);
}
}
public void swap(int one, int two){
AdjNode first = heap[one];
AdjNode second = heap[two];
map.put(first.nodeNumber, two);
map.put(second.nodeNumber, one);
AdjNode temp = heap[one];
heap[one] = heap[two];
heap[two] = temp;
}
public void constructHeap(){
for(int i=size-1; i>=0; i--){
int temp = i;
while(heap[temp].edgeCost < heap[(int)Math.floor(temp/2)].edgeCost){
swap(temp, (int)Math.floor(temp/2));
temp = (int)Math.floor(temp/2);
}
}
initializeMap();
}
public void updatevertices(int pluckedNode){
for(AdjNode adjacentNode : g.list[pluckedNode]){
if(!visited.contains(adjacentNode.nodeNumber)){
int positionInHeap = map.get(adjacentNode.nodeNumber);
if(adjacentNode.edgeCost < heap[positionInHeap].edgeCost){
// //System.out.println(adjacentNode.nodeNumber + " not visited, Updating vertice " + heap[positionInHeap].nodeNumber + " from " + heap[positionInHeap].edgeCost + " to " + adjacentNode.edgeCost);
// heap[positionInHeap].edgeCost = INF;
// //heap[positionInHeap].edgeCost = adjacentNode.edgeCost;
// int heapifiedIndex = heapifyAt(positionInHeap); // This code follows my logic
// heap[heapifiedIndex].edgeCost = adjacentNode.edgeCost; // (which doesnt work)
// //heapifyAt(size - 1);
heap[positionInHeap].edgeCost = adjacentNode.edgeCost;
//heapifyAt(positionInHeap);
constructHeap(); // When replaced by SiftDown,
} // works as charm
}
}
}
public void printSet(){
Iterator<Integer> it = visited.iterator();
System.out.print("Printing set : [");
while(it.hasNext()){
System.out.print((int)it.next() + ", ");
}
System.out.println("]");
}
public AdjNode pluck(){
AdjNode min = heap[0];
int minNodeNumber = heap[0].nodeNumber;
AdjNode toRet = new AdjNode(min.nodeNumber, min.edgeCost);
heap[0].edgeCost = INF;
constructHeap();
visited.add(minNodeNumber);
updatevertices(minNodeNumber);
return toRet;
}
public int heapifyAt(int index){
if(heap[index].edgeCost < heap[(int)Math.floor(index/2)].edgeCost){
while(heap[index].edgeCost < heap[(int)Math.floor(index/2)].edgeCost){
swap(index, (int)Math.floor(index/2));
index = (int)Math.floor(index/2);
}
}else{
if(index*2 + 2 < size){
while(index*2 + 2 < size && (heap[index].edgeCost > heap[index*2 + 1].edgeCost|| heap[index].edgeCost > heap[index*2 + 2].edgeCost)){
if(heap[index*2 + 1].edgeCost < heap[index*2 + 2].edgeCost){
//swap with left child
swap(index, index*2 + 1);
index = index*2 + 1;
}else{
//swap with right child
swap(index, index*2 + 2);
index = index*2 + 2;
}
}
}
}
return index;
}
}
static class Graph{
int numberOfVertices;
AdjList[] list;
Graph(int numberOfVertices){
list = new AdjList[numberOfVertices];
for(int i=0; i<numberOfVertices; i++){
list[i] = new AdjList();
}
this.numberOfVertices = numberOfVertices;
}
public void addEdge(int from, int to, int cost){
this.list[from].add(to, cost);
this.list[to].add(from, cost);
}
public void printGraph(){
System.out.println("Printing Graph");
for(int i=0; i<numberOfVertices; i++){
System.out.print(i + " = ");
list[i].printList();
}
}
}
public static void prims(Graph graph, Heap heap){
int totalMin = INF;
int tempSize = graph.numberOfVertices;
while(tempSize>0){
AdjNode min = heap.pluck();
totalMin += min.edgeCost;
System.out.println("Added cost : " + min.edgeCost);
tempSize--;
}
System.out.println("Total min : " + totalMin);
}
public static void main(String[] args) throws Throwable {
Scanner in = new Scanner(new File("/home/mayur/Downloads/PrimsInput.txt"));
Graph graph = new Graph(in.nextInt());
in.nextInt();
while(in.hasNext()){
graph.addEdge(in.nextInt() - 1, in.nextInt() - 1, in.nextInt());
}
Heap heap = new Heap(graph);
prims(graph, heap);
}
}
With a proper implementation of heap, you should be able to bubble up and down. Heap preserves a group of elements using an order that applies to both directions and bubbling up and down are essentially the same, apart from the direction in which you move.
As to your implementation, I believe you are correct but one, seemingly minor issue: indexing.
If you look around for array implementations of heap, you will notice that in most cases the root is located at index 1, instead of 0. The reason for that being, in a 1-indexed array you preserve the following relation between parent p and children c1 and c2.
heap[i] = p
heap[2 * i] = c1
heap[2 * i + 1] = c2
It is trivial to draw an array on a piece of paper and see that this relation holds, if you have the root at heap[1]. The children of root, at index 1, are located at indices 2 and 3. Children of the node at index 2 are at indices 4 & 5, while children of the node at index 3 are at indices 6 & 7, and so on.
This relation helps you get to the children or the parent of any node at i, without having to keep track of where they are. (i.e. parent is at floor(i/2) and children are at 2i and 2i+1)
What you seem to have tried is a 0-indexed implementation of heap. Consequently you had to use a slightly different relation given below for parent p and children c1 and c2.
heap[i] = p
heap[2 * i + 1] = c1
heap[2 * i + 2] = c2
This seems to be ok when accessing the children. For example, the children of root, at index 0, are located at indices 1 and 2. Children of the node at index 1 are at indices 3 & 4, while children of the node at index 2 are at indices 5 & 6, and so on. However there is a pickle when accessing the parent of a node. If you consider node 3 and take floor(3/2), you do get index 1, which is the parent of 1. However, if you take the node at index 4, floor(4/2) gives you index 2, which is not the parent of the node at index 4.
Obviously, this adaptation of the index relationship between a parent and its children does not work for both children. Unlike the 1-indexed heap implementation, you can not treat both children the same while accessing their parents. Therefore, the problem lies specifically in your bubbling up part, without necessarily being related to bubbling up operation. As a matter of fact, though I haven't tested your code, the bubbling up portion of heapifyAt function seems to be correct.(i.e. except the indexing, of course)
Now, you may keep using a 0-indexed heap and adapt your code so that whenever you are looking for a node's parent, you implicitly check whether it is the right (i.e. not as in correct but as in the opposite of left) child of that parent and use floor((i-1)/2) if it is. Checking whether a node is the right child is trivial: just look if it is even or not. (i.e. as you index right children with 2i + 2, they will always be even)
However I recommend you take a different approach and instead use a 1-indexed array implementation of heap. The elegance of the array implementation of heap is that you can treat each node the same and you don't have to do anything different based on its index or location, with the root of the heap perhaps being the only possible exception to this.
In an attempt to write a brute force maze solving C program, I've written this java program first to test an idea. I'm very new to C and intend to convert it after getting this right in java. As a result, I'm trying stick away from arraylists, fancy libraries, and such to make it easier to convert to C. The program needs to generate a single width path of shortest steps to solve a maze. I think my problem may be in fragmenting a path-storing array passed through each recursion. Thanks for looking at this. -Joe
maze:
1 3 3 3 3
3 3 3 3 3
3 0 0 0 3
3 0 3 3 3
0 3 3 3 2
Same maze solved by this program:
4 4 4 4 4
4 4 4 4 4
4 0 0 0 4
3 0 3 3 4
0 3 3 3 2
number notation are explained in code
public class javamaze {
static storage[] best_path;
static int best_count;
static storage[] path;
//the maze - 1 = start; 2 = finish; 3 = open path
static int maze[][] = {{1, 3, 3, 3, 3},
{3, 3, 3, 3, 3},
{0, 0, 0, 0, 3},
{0, 0, 3, 3, 3},
{3, 3, 3, 3, 2}};
public static void main(String[] args) {
int count1;
int count2;
//declares variables used in the solve method
best_count = 0;
storage[] path = new storage[10000];
best_path = new storage[10000];
int path_count = 0;
System.out.println("Here is the maze:");
for(count1 = 0; count1 < 5; count1++) {
for(count2 = 0; count2 < 5; count2++) {
System.out.print(maze[count1][count2] + " ");
}
System.out.println("");
}
//solves the maze
solve(findStart()/5, findStart()%5, path, path_count);
//assigns an int 4 path to the maze to visually represent the shortest path
for(int count = 0; count <= best_path.length - 1; count++)
if (best_path[count] != null)
maze[best_path[count].getx()][best_path[count].gety()] = 4;
System.out.print("Here is the solved maze\n");
//prints the solved maze
for(count1 = 0; count1 < 5; count1++) {
for(count2 = 0; count2 < 5; count2++){
System.out.print(maze[count1][count2] + " ");
}
System.out.print("\n");
}
}
//finds maze start marked by int 1 - this works perfectly and isn't related to the problem
public static int findStart() {
int count1, count2;
for(count1 = 0; count1 < 5; count1++) {
for(count2 = 0; count2 < 5; count2++) {
if (maze[count1][count2] == 1)
return (count1 * 5 + count2);
}
}
return -1;
}
//saves path coordinate values into a new array
public static void save_storage(storage[] old_storage) {
int count;
for(count = 0; count < old_storage.length; count++) {
best_path[count] = old_storage[count];
}
}
//solves the maze
public static Boolean solve(int x, int y, storage[] path, int path_count) {
//checks to see if grid squares are valid (3 = open path; 0 = wall
if (x < 0 || x > 4) { //array grid is a 5 by 5
//System.out.println("found row end returning false");
return false;
}
if (y < 0 || y > 4) {
//System.out.println("Found col end returning false");
return false;
}
//when finding finish - records the number of moves in static int best_count
if (maze[x][y] == 2) {
if (best_count == 0 || best_count > path_count) {
System.out.println("Found end with this many moves: " + path_count);
best_count = path_count;
save_storage(path); //copies path counting array into a new static array
}
}
//returns false if it hits a wall
if (maze[x][y] == 0)
return false;
//checks with previously crossed paths to prevent an unnecessary repeat in steps
for(storage i: path)
if (i != null)
if (i.getx() == x && i.gety() == y)
return false;
//saves current recursive x, y (row, col) coordinates into a storage object which is then added to an array.
//this array is supposed to fragment per each recursion which doesn't seem to - this may be the issue
storage storespoints = new storage(x, y);
path[path_count] = storespoints;
//recurses up, down, right, left
if (solve((x-1), y, path, path_count++) == true || solve((x+1), y, path, path_count++) == true ||
solve(x, (y+1), path, path_count++) == true || solve(x, (y-1), path, path_count++) == true) {
return true;
}
return false;
}
}
//stores (x, y) aka row, col coordinate points
class storage {
private int x;
private int y;
public storage(int x, int y) {
this.x = x;
this.y = y;
}
public int getx() {
return x;
}
public int gety() {
return y;
}
public String toString() {
return ("storage coordinate: " + x + ", " + y + "-------");
}
}
This wasn't originally intended to be an answer but it sort of evolved into one. Honestly, I think starting in Java and moving to C is a bad idea because the two languages are really nothing alike, and you won't be doing yourself any favors because you will run into serious issues porting it if you rely on any features java has that C doesn't (i.e. most of them)
That said, I'll sketch out some algorithmic C stuff.
Support Structures
typedef
struct Node
{
int x, y;
// x and y are array indices
}
Node;
typedef
struct Path
{
int maxlen, head;
Node * path;
// maxlen is size of path, head is the index of the current node
// path is the pointer to the node array
}
Path;
int node_compare(Node * n1, Node * n2); // returns true if nodes are equal, else false
void path_setup(Path * p, Node * n); // allocates Path.path and sets first node
void path_embiggen(Path * p); // use realloc to make path bigger in case it fills up
int path_toosmall(Path * p); // returns true if the path needs to be reallocated to add more nodes
Node * path_head(Path * p); // returns the head node of the path
void path_push(Path * p, Node * n); // pushes a new head node onto the path
void path_pop(Path * p); // pops a node from path
You might to change your maze format into an adjacency list sort of thing. You could store each node as a mask detailing which nodes you can travel to from the node.
Maze Format
const int // these constants indicate which directions of travel are possible from a node
N = (1 << 0), // travel NORTH from node is possible
S = (1 << 1), // travel SOUTH from node is possible
E = (1 << 2), // travel EAST from node is possible
W = (1 << 3), // travel WEST from node is possible
NUM_DIRECTIONS = 4; // number of directions (might not be 4. no reason it has to be)
const int
START = (1 << 4), // starting node
FINISH = (1 << 5); // finishing node
const int
MAZE_X = 4, // maze dimensions
MAZE_Y = 4;
int maze[MAZE_X][MAZE_Y] =
{
{E, S|E|W, S|E|W, S|W },
{S|FINISH, N|S, N|START, N|S },
{N|S, N|E, S|E|W, N|S|W },
{N|E, E|W, N|W, N }
};
Node start = {1, 2}; // position of start node
Node finish = {1, 0}; // position of end node
My maze is different from yours: the two formats don't quite map to each other 1:1. For example, your format allows finer movement, but mine allows one-way paths.
Note that your format explicitly positions walls. With my format, walls are conceptually located anywhere where a path is not possible. The maze I created has 3 horizontal walls and 5 vertical ones (and is also enclosed, i.e. there is a continuous wall surrounding the whole maze)
For your brute force traversal, I would use a depth first search. You can map flags to directions in a number of ways, like maybe the following. Since you are looping over each one anyway, access times are irrelevant so an array and not some sort of faster associative container will be sufficient.
Data Format to Offset Mappings
// map directions to array offsets
// format is [flag], [x offset], [y offset]
int mappings[][] =
{
{N, -1, 0},
{S, 1, 0},
{E, 0, 1},
{W, 0, -1}
}
Finally, your search. You could implement it iteratively or recursively. My example uses recursion.
Search Algorithm Pseudocode
int search_for_path(int ** maze, char ** visited, Path * path)
{
Node * head = path_head(path);
Node temp;
int i;
if (node_compare(head, &finish)) return 1; // found finish
if (visited[head->x][head->y]) return 0; // don't traverse again, that's pointless
visited[head->x][head->y] = 1;
if (path_toosmall(path)) path_embiggen(path);
for (i = 0; i < NUM_DIRECTIONS; ++i)
{
if (maze[head->x][head->y] & mappings[i][0]) // path in this direction
{
temp = {head->x + mappings[i][1], head->y + mappings[i][2]};
path_push(path, &temp);
if (search_for_path(maze, visited, path)) return 1; // something found end
path_pop(path);
}
}
return 0; // unable to find path from any unvisited neighbor
}
To call this function, you should set everything up like this:
Calling The Solver
// we already have the maze
// int maze[MAZE_X][MAZE_Y] = {...};
// make a visited list, set to all 0 (unvisited)
int visited[MAZE_X][MAZE_Y] =
{
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0}
};
// setup the path
Path p;
path_setup(&p, &start);
if (search_for_path(maze, visited, &path))
{
// succeeded, path contains the list of nodes containing coordinates from start to end
}
else
{
// maze was impossible
}
It's worth noting that because I wrote this all in the edit box, I haven't tested any of it. It probably won't work on the first try and might take a little fiddling. For example, unless start and finish are declared globally, there will be a few issues. It would be better to pass the target node to the search function instead of using a global variable.