What's wrong with my recursive function? - c++

So I'm trying to implement a recursive function that generates the entire game tree of Tic-Tac-Toe, and I can't seem to get it to work.
void BuildTree(Node& nNode, const int& nextPlayer)
{
//Copy last board
Ticboard tBoard = nNode.m_board;
do
{
//Return first valid move
int validMove = tBoard.FirstValidMove();
if (validMove != -1)
{
Node f;
Ticboard tempBoard = nNode.m_board;
tempBoard.Move(validMove, nextPlayer);
tBoard.Move(validMove, nextPlayer);
f.m_board = tempBoard;
f.m_winCount = 0;
nNode.m_branches.push_back(f);
int currPlay = (nextPlayer == 1 ? 2 : 1);
BuildTree(f,currPlay);
}
else
{
break;
}
}while(true);
}
The actual function works, I've gone through and debugged it and it SHOWS it working as it is supposed to, but when I look at the nodes generated (for Tic-Tac-Toe, by the way) in Visual Studios via breakpoint, it only shows the first 9 branches. I know more were generated because it takes a few seconds, and I added a counter.
Here's how I call the code:
Ticboard lol;
Node startTree;
startTree.m_board = lol;
int startPlay = 1;
BuildTree(startTree, startPlay);
Without copying all my code for bitboards and whatnot in here, can you see anything immediately wrong with the logic?

nNode.m_branches.push_back(f);
This will push_back a copy of the Node f, so the stuff inside nNode.m_branches will be irrelevant to the modification of f later on.

Related

How to transform a recursive function to an iterative one

I'm trying to convert this recursive function to an iterative one using a stack:
void GetToTownRecursive(int x, Country &country, AList *accessiblesGroup, vector<eTownColor> &cities_colors)
{
cities_colors[x - 1] = eTownColor::BLACK;
accessiblesGroup->Insert(x);
List *connected_cities = country.GetConnectedCities(x);
if (!connected_cities->IsEmpty())
{
ListNode *curr_city = connected_cities->First();
while (curr_city != nullptr)
{
if (cities_colors[curr_city->GetTown() - 1] == eTownColor::WHITE)
{
GetToTownRecursive(curr_city->GetTown(), country, accessiblesGroup, cities_colors);
}
curr_city = curr_city->GetNextNode();
}
}
}
The function takes a town number as an input and returns a list of towns that are connected to that town (directly as well as indirectly).
I'm having difficulty converting it because of the while loop within and because the only action taken after the recursive call is the promotion of the list iterator - curr_city. What should I push into the stack in this case?
Would be glad for your help!
The action taken after the recursive call is the whole remainder of the while loop (all the remaining iterations). On the stack, you have to save any variables that could change during the recursive call, but will be needed after. In this case, that's just the value of curr_city.
If goto was still a thing, you could then replace the recursive call with:
save curr_city
set x = curr_city->GetTown()
goto start
Then at the end, you have to
check stack
If there's a saved curr_city, restore it and goto just after (3)
Because it's not acceptable to use gotos for this sort of thing (they make your code hard to understand), you have to break up your function into 3 top-level parts:
part 1: all the stuff before the first recursive call, ending with 1-3
part 2: a loop that does all the stuff between recursive calls, ending with 1-3 if it gets to another recursive call, or 4-5 if it doesn't.
part 3: anything that happens after the last recursive call, which is nothing in this case.
Typically there is then a lot of cleanup and simplification you can do after this rearrangement.
The basic idea would be something like the following.
void GetToTown(int x, Country &country, AList *accessiblesGroup,
vector<eTownColor> &cities_colors)
{
Stack<int> pendingX = new ...
pendingX.push(x);
while (!pendingX.isEmpty()) {
int localX = pendingX.Pop();
cities_colors[localX - 1] = eTownColor::BLACK;
accessiblesGroup->Insert(localX);
List *connected_cities = country.GetConnectedCities(localX);
if (!connected_cities->IsEmpty())
{
ListNode *curr_city = connected_cities->First();
while (curr_city != nullptr)
{
if (cities_colors[curr_city->GetTown() - 1] == nColor::WHITE)
{
pendingX.Push(curr_city->GetTown());
}
curr_city = curr_city->GetNextNode();
}
}
}
}

Calling functions randomly using a vector

#assume everything needed is included
void Robot::moveRobot()
{
//calls a random directon for robot to move in
//if direction returns false (not able to move in that direction),
//call another random direction up to 4 times, excluding the one(s)
//already called. If they all return false, do not move the robot.
//vecDir = {moveForward(), moveBackward(), moveRight(), moveLeft()}
// = {0,1,2,3} initially
vector<int> vecDir{0,1,2,3}; //vetor indicating direction to move
int num = rand() % vecDir.size();
if(num == vecDir[0])
{
//if not able to move forward, try a different random direction
if(Robot::moveForward() == false)
{
vecDir.erase(num);
//here, vector will be vecDir={1,2,3}
}
}
else if(num == vecDir[1])
{
Robot::moveBackward();
}
else if(num == vecDir[2])
{
Robot::moveRight();
}
else //num == vecDir[3]
{
Robot::moveLeft();
}
}
Hi! I'm trying to randomly call these four functions within the moveRobot() function using a vector whose size is changed depending on if a direction cannot be called. I set moveForward() to the first element, moveBackward() to the second element, etc. If any of the moveXXXX() functions are false, I want to delete that element of the array. Example code shown
Example output:
//before doing anything, vecDir = {0,1,2,3}
int num = rand() % vecDir.size(); //assume num = 1, so it calls moveBackward()
//assume moveBackward() is false, so gets rid of that element
vecDir.erase(num); //new vecDir = {0,2,3};
// vecDir(0) would be moveForward(), vecDir(1) is now moveRight(), vecDir(1) is now moveLeft()
How would I continue this process to exhaust all elements and not move a robot? I know a for loop would be involved, but I cannot think of where to use it. I am also not sure if my thinking is correct by using if else for each element. Any help is appreciated, and I apologize if the question is confusing. I can clear it up if there are any misunderstandings.
Just have a vector of function pointers, rather then numbers.
void Robot::moveRobot() {
// vector of pointers to functions to move
std::vector<bool()> moves{
moveForward(), moveBackward(), moveRight(), moveLeft()
};
// we repeat the process until any moves are available.
while (moves.size() > 0) {
// pick a random move
const int num = rand() % moves.size();
// try to move
if (moves[num]() == true) {
// yay, we moved!
break;
}
// we did not move - remove current option and repeat
moves.erase(moves.begin() + num);
}
}

Checking for a cycle in an undirected graph using DFS?

So, I made the following code for DFS:
void dfs (graph * mygraph, int foo, bool arr[]) // here, foo is the source vertex
{
if (arr[foo] == true)
return;
else
{
cout<<foo<<"\t";
arr[foo] = true;
auto it = mygraph->edges[foo].begin();
while (it != mygraph->edges[foo].end())
{
int k = *it;
if (arr[k] == false)
{
//cout<<k<<"\n";
dfs(mygraph,k,arr);
//cout<<k<<"\t";
}
it++;
}
}
//cout<<"\n";
}
Now, I read up that in an undirected graph, if while DFS, it returns to the same vertex again, there is a cycle. Therefore, what I did was this,
bool checkcycle( graph * mygraph, int foo, bool arr[] )
{
bool result = false;
if (arr[foo] == true)
{
result = true;
}
else
{
arr[foo] = true;
auto it = mygraph->edges[foo].begin();
while (it != mygraph->edges[foo].end())
{
int k = *it;
result = checkcycle(mygraph,k,arr);
it++;
}
}
return result;
}
But, my checkcycle function returns true even if their is no cycle. Why is that? Is there something wrong with my function? There is no execution problem, otherwise I would have debugged, but their seems to be something wrong in my logic.
Notice that your function doesn't quite do what you think it does. Let me try to step through what's happening here. Assume the following relationships: (1,2), (1,3), (2,3). I'm not assuming reflexibility (that is, (1,2) does not imply (2,1)). Relationships are directed.
Start with node 1. Flag it as visited
Iterate its children (2 and 3)
When in node 2, recursively call check cycle. At this point 2 is also flagged as visited.
The recursive call now visits 3 (DEPTH search). 3 is also flagged as visited
Call for step 4 dies returning false
Call for step 3 dies returning false
We're back at step 2. Now we'll iterate node 3, which has already been flagged in step 4. It just returns true.
You need a stack of visited nodes or you ONLY search for the original node. The stack will detect sub-cycles as well (cycles that do not include the original node), but it also takes more memory.
Edit: the stack of nodes is not just a bunch of true/false values, but instead a stack of node numbers. A node has been visited in the current stack trace if it's present in the stack.
However, there's a more memory-friendly way: set arr[foo] = false; as the calls die. Something like this:
bool checkcycle( graph * mygraph, int foo, bool arr[], int previousFoo=-1 )
{
bool result = false;
if (arr[foo] == true)
{
result = true;
}
else
{
arr[foo] = true;
auto it = mygraph->edges[foo].begin();
while (it != mygraph->edges[foo].end())
{
int k = *it;
// This should prevent going back to the previous node
if (k != previousFoo) {
result = checkcycle(mygraph,k,arr, foo);
}
it++;
}
// Add this
arr[foo] = false;
}
return result;
}
I think it should be enough.
Edit: should now support undirected graphs.
Node: this code is not tested
Edit: for more elaborate solutions see Strongly Connected Components
Edit: this answer is market as accepted although the concrete solution was given in the comments. Read the comments for details.
are all of the bools in arr[] set to false before checkcycle begins?
are you sure your iterator for the nodes isn't doubling back on edges it has already traversed (and thus seeing the starting node multiple times regardless of cycles)?

Values of the function parameters are changing randomly (but they're not modified from the code)

I have to implement an NBC (for finding clusters in the provided set of data) algorithm at my class project with a friend. We came across very strange issue. There are few helper functions, and the one with a problem is kNN (possibly kEN too) in the kNB.h file. After passing arguments to it from the main function of the program (for example k=3 and p=5), it goes to the kNN function and starts changing values of k and p randomly, even though function code is not supposed to do that anywhere as you can see below.
Also, while using debugging mode and going through this function step by step I noticed that it sometimes comes back before the first while which I think shouldn't happen. I guess it may be some trivial mistake, but I'm not very good at C++ (unfortunately we were ordered to use it). You can download entire Visual Studio 2013 solution from here: https://dl.dropboxusercontent.com/u/1561186/EDAMI.zip. So, does anyone have any idea why described situation is happening?
static vector<int> kNN(int k, int p, Dataset<V>* records)
{
int b = p, f = p;
bool backwardSearch, forwardSearch;
vector<int> tmp;
LengthMetric<V>* lengthMetric = records->getLengthMetric();
backwardSearch = PrecedingPoint(records, b);
forwardSearch = FollowingPoint(records, f);
int i = 0;
while (backwardSearch && forwardSearch && i < k)
{
if (records->getRecord(p)->getLength() - records->getRecord(b)->getLength() < records->getRecord(f)->getLength() - records->getRecord(p)->getLength())
{
i++;
tmp.push_back(b);
backwardSearch = PrecedingPoint(records, b);
}
else
{
i++;
tmp.push_back(f);
forwardSearch = FollowingPoint(records, f);
}
}
while (backwardSearch && i < k)
{
i++;
tmp.push_back(b);
backwardSearch = PrecedingPoint(records, b);
}
while (forwardSearch && i < k)
{
i++;
tmp.push_back(f);
forwardSearch = FollowingPoint(records, f);
}
return tmp;
}
Look at second constructor of your class Dataset
Dataset(vector<Record<V>*> rrecords,
LengthMetric<V>* metric = new DumbLengthMetric<V>())
: records(rrecords),
lengthMetric(lengthMetric) { // <-------------------
lengthMetric(lengthMetric) does nothing. Changing it to lengthMetric(metric) I got some result on your project and no one variable was changed.
BTW, do not include in zip any stuff like folders Debug, Release and files *.sdf, *.ncb

How to resolve a bad_alloc that seems unlikely to be an out-of-memory issue?

I'm writing a bit of code for searching a maze with BFS in C++ (my primary language is Python, but I wanted to excersise my C++ brain a bit...), and I stumbled across this strange error.
Here are the relevant data structures:
struct Maze {
std::pair<int, int> start;
std::pair<int, int> goal;
std::pair<int,int> dims;
std::set<std::pair<int, int> > passable;
};
struct SearchNode {
std::pair<int, int> cell;
Maze* pMaze;
SearchNode* parent;
std::vector<SearchNode*> children;
};
Assume that I've already got a method void parseFile(Maze* maze, char* filename) that reads in a maze text file, storing the (row, col) pairs of the start and goal squares as well as a set corresponding to the (row, col) pairs that are "passable" in the maze.
There are a few other functions as well:
bool isPassable(Maze* maze, std::pair<int,int> testCell);
std::vector<SearchNode*> getPassableChildren(SearchNode sn);
void mazeSearch(Maze* maze);
Here are their implementations:
// <...snip...>
inline bool isPassable(Maze* maze, std::pair<int,int> cell) {
return maze->passable.find(cell) != maze->passable.end();
}
std::vector<SearchNode*> getPassableChildren(SearchNode sn) {
// Store a cached copy of the children, so if we require multiple queries
// we do not have to re-compute children.
if(sn.children.empty()) {
Maze* mazePointer = sn.pMaze;
int r = sn.cell.first;
int c = sn.cell.second;
for(int i = 0; i <= 2; ++i) {
for(int j = 0; j <= 2; ++j) {
if (!(i == 1 && j == 1)) {
std::pair<int,int> childCell(r+i-1, c+j-1);
if(isPassable(mazePointer, childCell)) {
// Build child SN
SearchNode child;
child.cell = childCell;
child.parent = &sn;
child.pMaze = mazePointer;
sn.children.push_back(&child);
}
}
}
}
}
return sn.children;
}
void mazeSearch(Maze* maze) {
std::set<std::pair<int,int> > visited;
std::deque<SearchNode> workQueue;
// Create root node.
SearchNode root;
root.cell = maze->start;
root.parent = NULL;
root.pMaze = maze;
workQueue.push_back(root);
visited.insert(root.cell);
while(!workQueue.empty()) {
SearchNode sn = workQueue.front();
workQueue.pop_front();
for(SearchNode* passableNeighbor : getPassableChildren(sn)) {
// THIS IF-STATEMENT IS BROKEN
if(passableNeighbor->cell.first == maze->goal.first &&
passableNeighbor->cell.second == maze->goal.second) {
printf("Found a path.\n");
return;
}
// Check to make sure it is not in our visited set.
// THIS STATEMENT IS ALSO BROKEN
if (visited.find(passableNeighbor->cell) == visited.end()) {
workQueue.push_back(*passableNeighbor);
visited.insert(passableNeighbor->cell);
}
}
}
printf("No path found.\n");
}
// <...snip...>
The code compiles fine under GCC 4.6.3: $g++ maze.cc -g -std=c++0x
However, $./a.out smallMaze.txt produces
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
I've done some sanity checking with Valgrind and GDB:
Valgrind points out that Conditional jump or move depends on uninitialised value(s) in the line that begins
if(passableNeighbor->cell.first == maze->goal.first
and the line nearby that does a set lookup,
if(visited.find(passableNeighbor->cell) == visited.end())
When I inspect these passableNeighbor pointers in GDB, it does look like the underlying SearchNode object hasn't had it's child cell initialized properly, with all sorts of weird values cropping up. I suspect that this has to do with my lack of understanding of how C++ allocates objects.
So it's pretty clear that the underlying issue is that the passableNeighbor object somehow has corrupt data in it. Is this an artifact of how I wrote the getPassableChildren() method? Any other thoughts?
I've looked around at std::bad_alloc and it seems like this exception is usually related to running out of memory, but I'm getting this error on my very first node expanded during BFS, so it seems extremely unlikely that I'm hitting any memory limit.
This part has a problem
if(isPassable(mazePointer, childCell)) {
// Build child SN
SearchNode child;
child.cell = childCell;
child.parent = &sn;
child.pMaze = mazePointer;
sn.children.push_back(&child);
}
in that it fills the children with pointers to a local variable. When you leave the if-statement, all the pointers are invalid.
If you create a new child here, you have better store its value than store a pointer.
You are adding to the children vector the address of a local variable, a big no-no
SearchNode child;
child.cell = childCell;
child.parent = &sn;
child.pMaze = mazePointer;
sn.children.push_back(&child);
Use some sort of allocation, or make your children be a vector<SearchNode>
E.g:
SearchNode *child = new SearchNode();
child->cell = childCell;
child->parent = &sn;
child->pMaze = mazePointer;
sn.children.push_back(child);
Then you will need to clean this up later, or make your vector vector<unique_ptr<SearchNode>> and push on unique_ptr<SearchNode>(child) and the de-allocation will be done for you