Jumping to function start from within certain code part - c++

include <iostream>
using namespace std;
int Solution(int i_start, int j_start, int i_end, int j_end, int s)
{
int row_dif=i_start-i_end;
int col_dif=j_start-j_end;
while (col_dif !=0 )
{
row_dif=i_start-i_end;
col_dif=j_start-j_end;
if ((row_dif>0) && (col_dif>0))
{
i_start=i_start-2;
j_start--;
}
if ((row_dif>0)) && (col_dif<0)
{
i_start=i_start-2;
j_start++;
}
if ((row_dif<0) && (col_dif>0 ))
{
i_start=i_start+2;
j_start--;
}
if ((row_dif<0) && (col_dif<0))
{
i_start=i_start+2;
j_start++;
}
if (row_dif=0)
{
if (col_dif>0)
{
j_start-2;
}
else if (col_dif<0)
{
j_start+2;
}
else //row_dif=0 dhe col_dif=0
{
cout<<"Problem solved "<<endl;
}
}
}
// col_dif=0
if (row_dif<=-4)
{
i_start=i_start+2;
j_start++;
}
if (row_dif>=4)
{
i_start=i_start-2;
j_start--;
}
}
I am trying to solve Red Knight shortest path with my own method but I am stuck at a part where I need to jump to function start. as an entry-condition I have decided to use row_dif=0 but when row_dif does reach 0 value, I also need to check if there could be more moves (row_dif>=4 or row_dif<=-4) available. And if there are available moves I need to jump to while loop again.

I am stuck at a part where I need to jump to function start
It seems to me like you are stumbling onto the idea of a recursive function. Something along the lines of
return Solution(i_start - 2, j_start - 1, i_end, j_end, s + 1)
Recursion causes the state to be pushed onto the program stack. This idea of a stack is important.
The Red Knight Shortest Path challenge looks to me an awful lot pathfinding. Specifically, A* pathfinding with constrained movements.
The recursive approach uses a stack and is depth-first. For a solution where you want to minimize moves, you want to use a breadth-first approach. You will still wind up using a stack, but your primary structure will be a queue.
As this challenge seems to be geared towards search algorithms, I would suggest studying up on everything I mentioned.

You should write a function int sign( int i ) that returns -1, 0 or +1 for integer less than, equal to or bigger than zero. Then all of your code becomes:
if( row_dif == 0 && col_dif == 0 ) {
// done interrupt
}
i_start -= 2 * sign( row_dif );
j_start -= 1 * sign( col_dif );
plus this code handles situation when col_dif is equal to 0, but row_dif is not, which you did not in your code.
To add your condition change your loop to:
while( true ) {
row_dif=i_start-i_end;
col_dif=j_start-j_end;
if( col_dif == 0 ) {
if( row_dif == 0 ) {
// done
break;
}
if( std::abs( row_dif ) < 4 )
break; // does not look right but follows your logic
col_dif = sign( row_dif );
}
i_start -= 2 * sign( row_dif );
j_start -= 1 * sign( col_dif );
}
Note: comparation operator in C++ is == not = and this is common mistake for novice C++ programmers.

Related

How can I optimize Astar for vast empty spaces?

I am creating a game with a 3D grid for flying entities, So I have a lot of points and connections in the air where there aren't any obstructions. I didn't want to decrease the resolution of my grid so I thought I could just skip over chunks (or empties as I call them) of the Astar map while they're not containing any obstructions, and I modified Godot's Astar algorithm to do this.
Unfortunately this ended up being slower than looping through points one at a time due to the way I implemented this modification, which needs to loop through all the edge points of an empty.
2D representation of how one edge point of an empty connects to all other edge points:
This ends up looping through a larger number of points than letting the A* algorithm work it's way through the empty.
So I'm sorta stumped on how to make this more efficient while still preserving the most optimal path.
I could potentially narrow down what faces of the empty should be scanned over by first comparing the center points of all 8 faces of the empty (as my grid consists of hexagonal prisms). Or maybe I should somehow use the face center points of the empty's faces exclusively instead of all edge points.
I mainly want to know if anyone has worked on an issue like this before, and if so what would be the recommended solution?
Here is the astar loop for reference:
bool AStar::_solve(Point *begin_point, Point *end_point, int relevant_layers) {
pass++;
//make sure parallel layers are supported
// or if *relevant_layers is 0 then use all points
bool supported = relevant_layers == 0 || (relevant_layers & end_point->parallel_support_layers) > 0;
if (!end_point->enabled || !supported) {
return false;
}
bool found_route = false;
Vector<Point *> open_list;
SortArray<Point *, SortPoints> sorter;
begin_point->g_score = 0;
begin_point->f_score = _estimate_cost(begin_point->id, end_point->id);
open_list.push_back(begin_point);
while (!open_list.empty()) {
Point *p = open_list[0]; // The currently processed point
if (p == end_point) {
found_route = true;
break;
}
sorter.pop_heap(0, open_list.size(), open_list.ptrw()); // Remove the current point from the open list
open_list.remove(open_list.size() - 1);
p->closed_pass = pass; // Mark the point as closed
//if the point is part of an empty, look through all of the edge points of said empty (as to skip over any points within the empty).
OAHashMap<int, Point*> connections;
PoolVector<Empty*> enabled_empties;
int size = p->empties.size();
PoolVector<Empty*>::Read r = p->empties.read();
for (int i = 0; i < size; i++) {
Empty* e = r[i];
supported = relevant_layers == 0 || (relevant_layers & e->parallel_support_layers) > 0;
//if the empty is enabled and the end point is not within the empty
if (e->enabled && supported && !end_point->empties.has(e)) {
enabled_empties.append(e);
//can travel to any edge point
for (OAHashMap<int, Point*>::Iterator it = e->edge_points.iter(); it.valid; it = e->edge_points.next_iter(it)) {
int id = *it.key;
Point* ep = *(it.value);
ep->is_neighbour = false;
//don't connect to the same point
if (id != p->id && (i == 0 || !connections.has(id))) {
connections.set(id, ep);
}
}
}
}
//add neighbours to connections
for (OAHashMap<int, Point*>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) {
int id = *it.key;
Point* np = *(it.value);// The neighbour point
np->is_neighbour = true;
//don't need to check for duplicate point connections if no empties
if (size == 0 || !connections.has(id)) {
//don't add points within enabled empties since they're meant to be skipped over
if (np->empties.size() > 0 && !np->on_empty_edge) {
bool in_enabled_empty = false;
PoolVector<Empty*>::Read r1 = np->empties.read();
for (int i = 0; i < np->empties.size(); i++) {
if (enabled_empties.has(r1[i])) {
in_enabled_empty = true;
break;
}
}
if (!in_enabled_empty) {
connections.set(id, np);
}
}
else {
connections.set(id, np);
}
}
}
for (OAHashMap<int, Point *>::Iterator it = connections.iter(); it.valid; it = connections.next_iter(it)) {
Point *e = *(it.value); // The neighbour point
//make sure parallel layers are supported
// or if *relevant_layers is 0 then use all points
supported = relevant_layers == 0 || (relevant_layers & e->parallel_support_layers) > 0;
if (!e->enabled || e->closed_pass == pass || !supported) {
continue;
}
real_t tentative_g_score = p->g_score + _compute_cost(p->id, e->id) * e->weight_scale;
bool new_point = false;
if (e->open_pass != pass) { // The point wasn't inside the open list.
e->open_pass = pass;
open_list.push_back(e);
new_point = true;
} else if (tentative_g_score >= e->g_score) { // The new path is worse than the previous.
continue;
}
e->prev_point = p;
e->prev_point_connected = e->is_neighbour;
e->g_score = tentative_g_score;
e->f_score = e->g_score + _estimate_cost(e->id, end_point->id);
if (new_point) { // The position of the new points is already known.
sorter.push_heap(0, open_list.size() - 1, 0, e, open_list.ptrw());
} else {
sorter.push_heap(0, open_list.find(e), 0, e, open_list.ptrw());
}
}
}
return found_route;
}
Note: I'm still not exactly sure what the sorter does.
the entire code can be seen here in a_star.cpp and a_star.h
Edit:
if anyone wants to reference or use this, I've modified the Astar code to add user-defined octants and to use a user-defined straight line function (they are user-defined so they can work with any type of grid) to be used between octants when possible to further decrease runtime, and it works very well in terms of speed. Though the pathing is not optimal, especially when adding a lot of obstacles/restricting the available positions.

Depth first search to find a shortest path c++

void existsInNextMapDFS(int currMapID, int startMapID, int destMapID, int numRecursions, cliext::vector<MapPath^>^ searchList, cliext::vector<MapPath^>^ finalPath,bool &destFound,int &i) {
if (currMapID == destMapID) {
if ((int)(finalPath->size()) == 0 || finalPath->size() > searchList->size())
*finalPath = searchList; //Current path is the shortest path to destination map
return; //Returning so that no further maps from this one are searched
}
if (getMap(currMapID)->portals->Count == 0 || numRecursions > 300) {
return;
}
//If current map is an endpoint or if number of recursions are over 300, no further maps are searched
for each(PortalData^ portalData in getMap(currMapID)->portals) {
Log::WriteLine("for loop portaldata");
bool existsInSearchList = false;
for each (MapPath ^ mapData in searchList) {
if (mapData->mapID == portalData->toMapID) {
Log::WriteLine("for loop mapdata");
existsInSearchList = true;
break;
}
}
if (getMap(portalData->toMapID) == nullptr) {
continue; //Skips portals where the portal's map is not found
}
if (existsInSearchList) {
continue; //Skip portals where it goes to maps already in search path to prevent loop backs
}
MapPath^ mapPath = gcnew MapPath(currMapID, portalData);
searchList->push_back(mapPath);
existsInNextMapDFS(portalData->toMapID, startMapID, destMapID, numRecursions + 1, searchList, finalPath,destFound,i); //Recursive call
searchList->pop_back();
}
Hey i'm trying to write a map skipper for a 2d platform game, each map has number of portal which are stored in map DATA, i need the shortest route to reach a destination map.
The idea is to go through all portals in each map until destination is reached and return the route.
this is what i got so far, but it gets stuck sometimes and doesn't search new maps.
i tried debugging it for hours but still couldnt find a sloution..

return does not stop function, Recursive function issue? (programming exercise, Dynamic Programming, Levenshtein Back-trace)

the printOptimalAlignment function is misbehaving. goto and return will not exit when the function reaches location (1,1)... where it should end, no crash and it stops at seemingly an arbitrary location of (6,6)... because for some reason it increments at the end of the function even though there is no increment-er for the values int yL, int xL, (but I don't follow why it calls itself if it gets to the end of the function without any "hits" on the if statements.
Full code:
https://repl.it/#fulloutfool/Edit-Distance
void printOptimalAlignment(int** arr, string y, string x,int yL, int xL){
int I_weight=1, D_weight=1, R_weight=1;
bool printinfo_allot = 1,printinfo = 1;
if(printinfo_allot){
cout<<"Location: "<<"("<<xL<<","<<yL<<")"<<"-------------------------------\n";
cout<<"Same check Letters: "<<x[xL-2]<<","
<<y[yL-2]<<"("<<(x[xL-2] == y[yL-2])<<")"<<"\n";
cout<<"LL: "<<"("<<xL-1<<","<<yL<<")"
<<":"<<arr[yL][xL-1]
<<":"<<(arr[yL][xL-1]+I_weight)
<<":"<<(arr[yL][xL])
<<":"<<(((arr[yL][xL-1]+I_weight) == arr[yL][xL])==1)
<<":"<<(yL>=1 && xL>=1)<<"\n";
cout<<"xL state:"<<((&x[xL]))<<":"<<(x[xL-1])<<"\n";
cout<<"yL state:"<<((&y[yL]))<<":"<<(y[yL-1])<<"\n";
string tx = &x[xL];
cout<<x.length()<<","<<(tx.length()+1)<<"\n";
}
string tx = &x[xL]; // slopy hotfix
if(x.length()==(tx.length()+1)){
cout<<"return functionality not working?-=-=-=-=-=-=-=-=\n";
cout<<"-> Prep last, current distance = "<<arr[yL][xL] <<"\n";
return;
//printOptimalAlignment(arr,y,x,yL-1,xL-1);
//cant use this goto... but where does it go?
//goto because_Im_a_terrible_person;
throw "how?... breaking rules... make it stop";
}
if(yL>=1 && xL>=1 && (x[xL-2] == y[yL-2]) == 1){
if(printinfo){
cout<<"-> Same (same char), current distance = "<<arr[yL][xL] <<"\n";
}
printOptimalAlignment(arr,y,x,yL-1,xL-1);
}
if(yL>=1 && xL>=1 && (arr[yL-1][xL-1] == arr[yL][xL])){
if(printinfo){
cout<<"-> Swap (same int), current distance = "<<arr[yL][xL] <<"\n";
if(arr[yL-1][xL-1]==0)cout<<"---this is last---\n";
}
printOptimalAlignment(arr,y,x,yL-1,xL-1);
}
if(yL>0 && xL>0 && (arr[yL-1][xL]+D_weight == arr[yL][xL])){
if(printinfo){
cout<<"-> Delete, current distance = "<<arr[yL][xL]<<"\n";
}
printOptimalAlignment(arr,y,x,yL-1,xL);
}
//really weird ((yL>1 && xL>1) && (((arr[yL][xL-1]+I_weight) == arr[yL][xL])==1))
//not true if it is?
bool seperate = (((arr[yL][xL-1]+I_weight) == arr[yL][xL])==1);
if(yL>=1 && xL>=1){
if((((arr[yL][xL-1]+I_weight) == arr[yL][xL])==1) && (true)){
if(printinfo){
cout<<"-> Insert, current distance = "<<arr[yL][xL]<<"\n";
cout<<"Next Location1: "<<"("<<xL-1<<","<<yL<<")"<<"\n";
}
printOptimalAlignment(arr,y,x,yL,xL-1);
return;
//how does it get here... also return gets ignored... prob another stack issue
cout<<"insert function broke?????? # (1,1) ???????????????\n";
//return;
}
}
return;
cout<<"END... Hopefully.. if you see this Something went wrong\n";
because_Im_a_terrible_person:
cout<<"QUIT\n";
}
I suspect your problem is that your function calls itself and you don't appear to be taking into account what should happen next after that call to itself finishes. So you get to your finish condition where you say the return doesn't work, but it does... it just returns to where you left off in the previous call to printOptimalAlignment, which still might do something before returning to its caller, and so on. You have three different sites where you recursively call printOptimalAlignment that aren't immediately followed by a return statement, and at any of these it might be that the code will continue and trigger another of your conditional blocks.

Breaking out of if statement

I am writing a program in which I use an if statement to check some condition; if true I increment a counter. The problem is that as soon as the statement is true the variable either gets incremented endlessly or by random number.
I have been trying to use some clause to break out of this statement if condition meet but with no luck
my code:
if(res_vect_angle >=60 && res_vect_angle <=100 && left_mag_b >100)
{
//line(drawing, *iter_s, *(iter_s -1), Scalar( 255, 255, 255 ), 2,8 );
left_hook_count++;
cout<<"Left Hook:..........................!!! "<<left_hook_count<<endl;
if(left_hook_count++ == true)
{
break;
}
}
The whole chunk of code associated with the issue:
float M1, M2;
float A1, A2;
double left_mag_a, left_mag_b;
double res_vect_angle;
int i = 0;
for(vector<Point>::iterator iter_lh = Leftarm.begin(); iter_lh != Leftarm.end(); ++iter_lh)
{
if(iter_lh->y <=240 && iter_lh->y >=60 && iter_lh->x >=340 && iter_lh->x <=680)
{
left_detect.push_back(*iter_lh);
if(i % 4 == 0)
{
if(left_detect.size()>4)
{
for(vector<Point>::iterator iter_s = left_detect.begin()+3; iter_s != left_detect.end(); ++iter_s, i++)
{
//Resultant Magnetude
M1 = pow((double) iter_s->x + (iter_s -2)->x,2);
M2 = pow((double) iter_s->y + (iter_s -2)->y,2);
left_mag_a = (M1 + M2);
left_mag_b = sqrt(left_mag_a);
//Resultant Angle
A1 = abs(iter_s->x - (iter_s -2)->x);
A2 = abs(iter_s->y - (iter_s -2)->y);
res_vect_angle = abs(atan2(A1,A2) * 180 /PI);
//cout<<"LEFT HOOK ANGLE IS: "<<res_vect_angle<<endl;
if(res_vect_angle >=60 && res_vect_angle <=100 && left_mag_b >100)
{
//line(drawing, *iter_s, *(iter_s -1), Scalar( 255, 255, 255 ), 2,8 );
left_hook_count++;
cout<<"Left Hook:..........................!!! "<<left_hook_count<<endl;
if(left_hook_count++ == true)
{
break;
}
}
}
}
}
}
}
Hope this helps guys ps. left_hook_count++; is a int variable declared on top of my main().
The best solution is probably to invert the test, and make all the rest of the outer if conditional:
if (whatever) {
// do some stuff
if (left_hook_count != true) { // or whatever the test should really be
// do some more stuff
}
}
You could get the program flow you want using goto with a label after the outer if, but you don't want to.
On the other hand, it sounds like perhaps this is in a loop, and you don't want to enter the if block at all if the counter has been incremented? In that case you want:
if (left_hook_count == 0 && whatever) {
// do some stuff
}
you could provide more details so that we can figure out whats happening.
You might not have initialized it?
and checking again
if(left_hook_count++ == true)
it will increment it again unneccessariy and for for first count (0 : it wont happen)
i guess you 're using some recursive function. so check for Break condition (all test cases too).
Don't compare left_hook_count++ to true. In this context, true is equal to 1, and once left_hook_count exceeds 1, this test will fail and the code will never hit the break.
And you don't break out of an if statement. You break out of a loop; a break in an if statement inside the loop is one way of doing this.
You can just negate the condition, instead of trying to break out of the if:
if(...) {
if(!left_hook_count++) {
// Do what you need to do
}
}
my new answer:
:mylabel if (some_condition)
{
//code
if (some_condition) {break mylabel;}
//code
}
my old answer: Replace the if statement with a while statement containing a unconditional break at the end.
(old answer was before I learned of attaching labels to statement blocks.)
In your case:
while(res_vect_angle >=60 && res_vect_angle <=100 && left_mag_b >100)
{
//line(drawing, *iter_s, *(iter_s -1), Scalar( 255, 255, 255 ), 2,8 );
left_hook_count++;
cout<<"Left Hook:..........................!!! "<<left_hook_count<<endl;
if(left_hook_count++ == true)
{
break;
}
break; //this unconditional break makes the while loop act as an if statement
}
However if you don't have code after the conditional break what's the point of having it? I'm assuming you've omitted that code? The way you wrote it it would simply break out of the inner for loop.

C++ procedure for determining whether two segments intersect

I'm working a bit with computational geometry lately, and I am trying to find a way of checking whether two line segments intersect. I thought that I can use counterclockwise direction (CCW for short) to determine that. Here is my code so far:
struct point { double x, y };
double CCW(point a, point b, point c)
{ return (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x); }
int intersect(point a, point b, point c, point d)
{ return (CCW(a,b,c)*CCW(a,b,d)<0 && CCW(c,d,b)*CCW(c,d,a)<0); }
The above code worked for the test cases I entered, and it's pretty readable and very easy to implement. But after searching on the web, I found an other way of solving the segment intersection problem. The code is similar to mine, but it has some more if statements that my implementation omits. Here is the code:
struct line { point s, e; };
int middle(int a, int b, int c) {
int t;
if ( a > b ) {
t = a;
a = b;
b = t;
}
if ( a <= c && c <= b ) return 1;
return 0;
}
int intersect(line a, line b) {
if ( ( CCW(a.s, a.e, b.s) * CCW(a.s, a.e, b.e) < 0 ) &&
( CCW(b.s, b.e, a.s) * CCW(b.s, b.e, a.e) < 0 ) ) return 1;
if ( CCW(a.s, a.e, b.s) == 0 && middle(a.s.x, a.e.x, b.s.x) && middle(a.s.y, a.e.y, b.s.y) ) return 1;
if ( CCW(a.s, a.e, b.e) == 0 && middle(a.s.x, a.e.x, b.e.x) && middle(a.s.y, a.e.y, b.e.y) ) return 1;
if ( CCW(b.s, b.e, a.s) == 0 && middle(b.s.x, b.e.x, a.s.x) && middle(b.s.y, b.e.y, a.s.y) ) return 1;
if ( CCW(b.s, b.e, a.e) == 0 && middle(b.s.x, b.e.x, a.e.x) && middle(b.s.y, b.e.y, a.e.y) ) return 1;
return 0;
}
Could someone explain which is the difference between the two implementations, and which is safer to use? Thanks in advance.
The function that you found is also checking the case where the line segments lie within the same line. In that case, it becomes a one-dimensional problem of finding whether the two line segments overlap. Your code would return false in this case. Whether this is preferred or not depends on the application.
Example:
point a={1,0}, b={3,0}, c={2,0}, d={4,0};
intersect(a,b,c,d); // your function will return false,
// but the one you found will return true
The function you found also looks at cases where the endpoint of one line-segment lies along the other line segment:
Example:
point a={1,0}, b={3,0}, c={2,0}, d={2,3};
intersect(a,b,c,d); // your function will return false,
// but the one you found will return true