I have a BFS that is supposed to solve a maze that currently only solves short mazes and returns a segfault for other mazes
this algorithm is supposed to add to a vector a path as long as there are no junctions and if there are any junctions it is supposed to create two equally long vectors each following a single path.
std::vector<MazeNode> solveBFS(Maze &a_maze){
MazeNode * NextNode = a_maze.getFirstNode();
std::vector<MazeNode*> Final;
std::vector<MazeNode> Finals;
std::queue<vector<MazeNode*> > Qvec;
NextNode->setVisited();
Final.push_back(NextNode);
Qvec.push(Final);
while(!Qvec.empty() && Qvec.front().at(Qvec.front().size()-1) != a_maze.getLastNode()){
cout << *Qvec.front().at(Qvec.front().size()-1) << endl;
std::vector<MazeNode*> TempV = Qvec.front();
MazeNode * Top = TempV.back();
Qvec.pop();
for(directions::nesw dir = directions::NORTH; dir < directions::WEST; dir = directions::nesw(dir + 1)){
if(canTravel(Top->getDirectionNode(dir))){
NextNode = Top->getDirectionNode(dir);
NextNode->setVisited();
NextNode->setVisited();
TempV.push_back(NextNode);
Qvec.push(TempV);
TempV.pop_back();
}
}
}
for(int i = 0; i < Qvec.front().size(); i++){
Finals.push_back(* Qvec.front()[i]);
}
return Finals;
}
Related
Could anyone point the flaw in the code?
The idea that I used is backtracking with recurrence and I would like to stick to this way of sloving the given problem. When the variable moves is <= 60 couple of answers are printed instantly though the program is still running. If moves = 61,62 it takes couple of minutes to print some solutions and if moves = 63 no solution is printed within 15 mins in both cases the program is still running.
Here is the code:
//checking on which move was the square visited
int board[8][8] = {{1,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}};
int x = 0;//x and y coordinate of the knight's placement
int y = 0;
//move knight by
int move_to[8][8] = {{1,2},{-1,-2},{-1,2},{1,-2},{2,1},{-2,-1},{-2,1},{2,-1}};
//how many moves have been done
int moves = 0;
void solve()
{
//printing one solution
if(moves==63)
{
for(int k = 0; k < 8; k++)
{
for(int n = 0; n < 8; n++)
cout << setw(2) << board[k][n] << " ";
cout << "\n";
}
cout << "--------------------\n";
return;
}
else
{
for(int i = 0; i < 8; i++)
{
//checking if knight is not leaving the board
if(x+move_to[i][0]<0 || x+move_to[i][0]>7 || y+move_to[i][1]<0 ||
y+move_to[i][1]>7 || board[x+move_to[i][0]][y+move_to[i][1]]>0)
continue;
//moving theknight
x+=move_to[i][0];
y+=move_to[i][1];
//increasing the moves count
moves++;
//marking the square to be visited
board[x][y] = moves+1;
//backtracking
solve();
board[x][y] = 0;
x-=move_to[i][0];
y-=move_to[i][1];
moves--;
}
}
}
int main()
{
solve();
return 0;
}
I remember this problem from study. I do not fix them but I change initial position then the first path is found faster (that is how I passed this lab ;P). It is normal because
the number of path is too big.
But you can:
choose from move_to in random order
use multiple threads
Other hand you can read about "Constraint Programming"
Hi guys!
I want to switch to UE4 and am now trying to repeat the function of finding a way by waypoints, it works well in Unity, but there were problems in C ++. the function turned out with an infinite loop, as I understand it, openList cannot become empty. my c ++ knowledge is not enough to solve the problem. I will be glad of any help!
TArray<FVector> UWaypointsPathfinding::GetPath(UWaypoint* startNode, UWaypoint* goalNode)
{
UWaypoint* beginNode = startNode;
set<UWaypoint*> openList;
vector<UWaypoint*> closedList;
openList.insert(startNode);
startNode->previous = nullptr;
startNode->distance = 0;
while (!openList.empty())
{
startNode = *openList.begin();
openList.erase(openList.begin());
float dist = startNode->distance;
closedList.push_back(startNode);
if(startNode == goalNode) break;
int l = startNode->nearest.Num();
for (int i = 0; i < l; i++)
{
UWaypoint* node = startNode->nearest[i]->FindComponentByClass<UWaypoint>();
if(find(closedList.begin(),closedList.end(),node) != closedList.end() || openList.find(node) != openList.end())
continue;
node->previous = startNode;
node->distance = dist + FVector::Dist(node->GetOwner()->GetActorLocation(), startNode->GetOwner()->GetActorLocation());
node->distance += FVector::Dist(node->GetOwner()->GetActorLocation(), goalNode->GetOwner()->GetActorLocation());
openList.insert(startNode);
}
}
// create path...
return TArray<FVector>();
}
supposedly the problem is in this piece
if(startNode == goalNode) break;
int l = startNode->nearest.Num();
for (int i = 0; i < l; i++)
{
UWaypoint* node = startNode->nearest[i]->FindComponentByClass<UWaypoint>();
if(find(closedList.begin(),closedList.end(),node) != closedList.end() || openList.find(node) != openList.end())
continue;
node->previous = startNode;
node->distance = dist + FVector::Dist(node->GetOwner()->GetActorLocation(), startNode->GetOwner()->GetActorLocation());
node->distance += FVector::Dist(node->GetOwner()->GetActorLocation(), goalNode->GetOwner()->GetActorLocation());
openList.insert(startNode);
}
The logic is strange so this is a mistype probably.
You insert startNode to openList at the beginning, then erase it in the loop and insert again. So the openList will always have a single member startNode and all cycles are identical.
Perhaps you meant openList.insert(node); instead of openList.insert(startNode); at the last line of the loop?
The graph:
and how the points are connected:
the file how points are connected are the output i have . The expected output should be 1<->216 , 23<->157 115<->157 and then 115<->216 . The order doesn't matter but those points should be connected this way
Let me ask you a question.
I have the following code:
for (int i = 0; i < values.size()-1;i++)
{
int result = 0;
double Min2 = DBL_MAX;
int x = 0;
for (int j = i+1; j < values.size(); j++)
{
/*if (visited[j] == false)*/
{
distance = sqrt(pow((values[i].x2 - values[j].x2), 2) + pow((values[i].y2 - values[j].y2), 2));
if (distance < Min2 && distance != 0)
{
Min2 = distance;
x = j;
}
}
}
If you look at the graph the left first node is 1 then goes 216 then 115 then 157 and then 23. I have the right connection except for 216-115 but instead of it connects 216-157. Why does it ignore or min distance won't help. I tried to use flag( like if visited or not)the same result. All nodes work , just this one doesn't want to be connected right.
The logic of the code seems a bit odd...
for (int i = 0; i < values.size()-1;i++) {
int result = 0;
double Min2 = DBL_MAX;
int x = 0;
for (int j = i+1; j < values.size(); j++) {
iterating till size()-1 seems like you assume that the relation "closest neighbour" is commutative, but it is not. Consider this example:
a b c
a has b as closest node and (by chance) also b has a as closest node, but c has b as closest node and this connection you would miss.
Further, starting the second loop at i+1 seems rather odd, as it assumes that the points in the vector are already ordered (if this would be the case, then whats the point of searching the closest nodes?).
If you know already, that the nodes are along a route, then I would do it like this:
1) start with the first node n0 in the route (its a bit more complicated if you dont know this node)
2) find the closest node to n0 call it n1
3) continue to find the closest node to ni among the nodes that are not yet connected to the route, call it ni+1
4) repeat 3) until you reach the end of the route.
I have the impression, that you dont understand the difference between those steps and your code. I dont like to give up, so I will try to explain again in a less pseudo way:
int currentNode = startNode; // as mentioned before, if you dont know
// this its a bit more involved
std::vector<int> route;
route.push_back(currentNode);
while (currentNode != endNode) { // also knowing the last node of the route helps...
double minDistance = std::numeric_limits<double>::max();
int nextNode = -1;
for (int i=0;i<nodes.size();i++) {
if (std::find(route.begin(), route.end(), i) == route.end()){
double distance = getDistance(currentNode,i);
if (distance < minDistance) {
minDistance = distance;
nextNode = i;
}
}
}
route.push_back(nextNode);
currentNode = nextNode;
}
Your outer loop shouldnt iterate through all nodes, if you actually want to find only that one route. Also you have to remember nodes that are already in the route (in case each node should appear only once and you dont want a closed loop).
for (int i = 0; i < values.size();i++)
{
int result = 0;
double Min2 = DBL_MAX;
int x = 0;
for (int j =0; j < values.size(); j++)
{
/*if (visited[j] == false)*/
{
distance = sqrt(pow((values[i].x2 - values[j].x2), 2) + pow((values[i].y2 - values[j].y2), 2));
if (distance < Min2 && distance != 0)
{
Min2 = distance;
x = j;
}
}
}
/*visited[i] = true;*/
I'm trying to implement backtracing of the vertices visited for the lowest costing route to a vertex. I'm getting incorrect results and don't understand why. The only correct output was the last one in the image. What is causing the incorrect
Note: driverMap is a 2D 14x14 integer vector that holds the distances it takes to get to each vertex and path is a int array to hold the past path vertex taken. The beginning is a section of the code from my Main function to help out.
It's different as my previous questions were different, this time i'm asking for help on my current output against expected when attempting to backtrace.
for(int i = 0; i < allCars.size(); i++) //allCars.size()
{
int startInt = allCars[i].getStart(), loopEnder = 0;
for(int k = 0; k < driverMap.size(); k++)
{
path[k] = 0;
Distances[k] = 0;
}
for(int j = 0; j < driverMap.size(); j++)
{
Distances[j] = driverMap[startInt][j];
}
cout << "\nSTART INTERSECTION: '" << startInt << "' END INTERSECTION: '" << allCars[i].getEnd() << "'" << endl;
Dijkstra(driverMap, Distances, path, startInt);
int endInt = allCars[i].getEnd(), atInt = path[endInt];
cout << "END = " << endInt;
//allCars[i].addPath(endInt);
do
{
cout << "AT = " << atInt;
allCars[i].addPath(atInt);
atInt = path[atInt];
loopEnder++;
}while(atInt != endInt && loopEnder < 5);
cout << endl;
//allCars[i].addPath(startInt);
allCars[i].displayCar();
}
void Dijkstra(const vector< vector<int> > & driverMap, int Distances[], int path[], int startInt)
{
int Intersections[driverMap.size()];
for(int a = 0; a < driverMap.size(); a++)
{
Intersections[a] = a;
}
Intersections[startInt] = -1;
for(int l = 0; l < driverMap.size(); l++)
{
int minValue = 99999;
int minNode = 0;
for (int i = 0; i < driverMap.size(); i++)
{
if(Intersections[i] == -1)
{
continue;
}
if(Distances[i] > 0 && Distances[i] < minValue)
{
minValue = Distances[i];
minNode = i;
}
}
Intersections[minNode] = -1;
for(int i = 0; i < driverMap.size(); i++)
{
if(driverMap[minNode][i] < 0)
{
continue;
}
if(Distances[i] < 0)
{
Distances[i] = minValue + driverMap[minNode][i];
path[i] = minNode;
continue;
}
if((Distances[minNode] + driverMap[minNode][i]) < Distances[i])
{
Distances[i] = minValue + driverMap[minNode][i];
path[i] = minNode;
}
}
}
}
Doing backtracking in djikstra
Record the node that update the value of the current node with a smaller value
// Every time you update distance value with a smaller value
Distances[i] = minValue + driverMap[minNode][i];
back[i] = minNode; //Record the node with an int array, should be something like this
After you have complete all djikstra looping. Backtrack from any point except the start point.
Say, we want to trace from pt 5 to pt 0 in your graph where pt 5 is starting point. We start at 0, take back[0] (should equal to 4), then we take back[4] (should equal to 8), then we take back[8] (should equal to 5), then we should have some kinds of mechanism to stop here as pt 5 is a starting point. As a result, you get 0-4-8-5 and you reverse the order. You get the path 5-8-4-0.
In my approach, pathTaken[minNode].push_back(i); is not using. You might need to initiate the int array back[] with starting point's value for those who is connected to starting point.
Edit Part
You miss the point: "You might need to initiate the int array back[] with starting point's value for those who is connected to starting point".
path[k] = 0; is wrong. You should not initiate path with fixed index for all cases. Instead, you should initiate with startInt (for those directly connected to starting node) and non-exist node index -1 (for those not directly connected to starting node)
What back-tracking doing is
to record which node provides a new minimum Cost to current node (and keep updating in dijkstra loop). At the end, every node will get a node value (back[i] in my case) that point to a node that provides node i with its minimize Cost.
Base on the concept of dijkstra algorithm with back-tracking, back[i] is the previous node in the path from starting node to node i. That mean the path should be looks like :
(start node)->(path with zero or more nodes)->node point by back[i]-> node i
Applying this concept, we can track the path backward with back[i], back[back[i]], back[back[back[i]]],...
Any why path[k] = 0; is wrong? In your code, your starting node is not always node 0, but startint. Consider case like startint = 13 and your target destination node is 11. Obviously, the path is 13-11. For node 11, it will never encounter Distances[i] = minValue + driverMap[minNode][i]; when startint = 13 in your coding because that is first minimum cost node. And what have you set? node 11 has back[11]=0 (initialization) which state that the previous node in the path node 13 to 11 is node 0 which is obviously incorrect in concept and back[0]=0 (best path from 13 to 0 is 13-0, no update also) which will loop to itself as 0=back[back[0]]=back[back[back[0]]]=....
In djikstra if you go backwards (finnish -> start) just pick lowest cost node at each step to reach staring point. This works after you have solved graph and you have each node evaluated/costed.
I am new in programming and working on c++ (even the concept of problem is same in c, I guess).
I am reading a file as sole arguments which contains alphabtes(symbols in my code) like "aabbacceaad" to calculate frequency.
My code calculate frequency correctly.I am sure of that.
The problem is that in my code Node *tree pointer variable (which is of type node). I am using it to create tree.But when i try to create tree from the frequency calculated from repeated symbols then this tree pointer variable only remembers the last executed frequency outside the for-loop. Please take care i just have to use pointers not arrays.
I mean suppose i have symbols in input file like this "aabcddeeebbaa". And the expected output for it is this:
0 symbol:a Freq:4 Left 0 Right 0 Index1
1 symbol:b Freq:3 Left 0 Right 0 Index2
2 symbol:c Freq:1 Left 0 Right 0 Index3
3 symbol:d Freq:2 Left 0 Right 0 Index4
4 symbol:e Freq:3 Left 0 Right 0 Index-1
But the output of my code is like this:
0 symbol:e Freq:3 Left:0 Right:0 Next:5 //Last "e" is executed,tree variable forgot a,b,c and d.
1 symbol:e Freq:3 Left:0 Right:0 Next:5
2 symbol:e Freq:3 Left:0 Right:0 Next:5
3 symbol:e Freq:3 Left:0 Right:0 Next:5
4 symbol:e Freq:3 Left:0 Right:0 Next:-1
My full c++ code to do so is :
#include <iostream>
#include <stdlib.h>
#include <fstream>
#include <cassert>
#include <vector>
using namespace std;
class Huffman {
public: int data_size,
length;
Huffman(char * argv);
~Huffman() {};
vector < char > storesym;
vector < int > storefreq;
struct Node
{
int value;
int freq, next;
short flag;
unsigned char symbol;
struct Node * left, * right;
};
Node * tree;
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTOR definition ////////////////////////////////////////////////////////////////////////////////
Huffman::Huffman(char * argv)
{
char c;
int count = 0;
int flag[256]; //this flag is to know if the alphabet is already counted or not.If counted that i set it to "1" other wise it is "0".Please see below in my code
int j = 0;
FILE * input_file;
int *symbolarray;
symbolarray=new int[30];
char i, n;
input_file = fopen(argv, "rb");
c = fgetc(input_file);
////////////////////////////////////////////////////////////////////////////// From here to down i read the alphabbets from file taken as sole argument ///////////////////////////////////////
while (c != EOF && c != '\n' && c != '\r')
{
symbolarray[count] = c;
count++;
c = fgetc(input_file);
}
fclose(input_file);
for (i = 0; i < count; i++)
flag[i] = {0 };
int fcount1 = 0;
for (i = 0; i < count; i++)
{
if (flag[i] == 0)
{
for (j = i; j < count; j++)
{
if (symbolarray[i] == symbolarray[j]&& flag[j] == 0)
{
fcount1++;
flag[j] = 1; //**I am setting flag to 1 those alphabets to 1 so that they will not be counted again on next iteration**
}
}
storesym.push_back(symbolarray[i]);
storefreq.push_back(fcount1);
}
fcount1 = 0;
}
cout << endl;
////////////////////////////////////////////////////////////////////////// ERROR PRONE PART STARTS NOW /////////////////////////////////////////////////////
for (i = 0; i < storesym.size(); i++)
{
tree = new Node; // the problem is here this tree pointer don't store the values for all alphabets, it just remembers the last executed alphabet after this for loop.
tree -> left = NULL;
tree ->right = NULL;
tree -> symbol = storesym[i];
tree -> freq = storefreq[i];
tree -> flag = 0;
tree -> next = i + 1;
cout<<"check1 : "<<tree -> symbol<<endl;
}
//////////////////////////////////////////////////////////////////// eror PRONE PART ENDS HERE ///////////////////////////////////////////////////////////////////////////////////
cout << "Here is the data read from file" << endl;
n = storesym.size() - 1;
for (int i = 0; i < storesym.size(); i++)
{
if (n == i)
{
tree -> next = -1;
cout << i << " symbol:" << tree -> symbol << " Freq:" << tree ->freq << " Left:" << tree -> left << " Right:" << tree -> right << " Next:" << tree -> next << endl;
break;
} else
{
cout << i << " symbol:" << tree -> symbol << " Freq:" << tree -> freq << " Left:" << tree -> left << " Right:" << tree ->right << " Next:" << tree -> next << endl;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
int main(int argc, char * * argv)
{
int freq[256] = {0};
if (argc < 2) {
cout << "Ohh.. Sorry , you forgot to provide the Input File please" << endl;
return (0);
}
Huffman Object1(argv[1]);
return (0);
}
**Please help me how to keep in memory all the "a,b,c,d and e" (Not just last "e") ? I know there is something to be done with pointers only.
This bit
while (c != EOF && c != '\n' && c != '\r')
{
tree[count].symbol = c;
count++;
c = fgetc(input_file);
}
dereferences the uninitialized pointer tree.
This is a big no-no, and means that your program is formally undefined.
You've just been unlucky in that it hasn't crashed.
You're doing it again a bit further down.
Then you allocate in this loop:
for (i = 0; i < storesym.size(); i++)
{
tree = new Node; // the problem is here this tree pointer don't store the values for all alphabets, it just remembers the last executed alphabet after this for loop.
tree -> left = NULL;
tree ->right = NULL;
tree -> symbol = storesym[i];
tree -> freq = storefreq[i];
tree -> flag = 0;
tree -> next = i + 1;
cout<<"check1 : "<<tree -> symbol<<endl;
}
which repeatedly allocates one Node and points tree at it.
In other words, it's not building a tree, and you need to rewrite it so it actually does.
Whatever course material you're following should have covered trees recently.
The best advice I can give is: start over, read more, and don't write so much code before testing.