Is a throw good in recursion? - c++

So this toy problem is a graph problem using dfs to see if this entire course schedule is valid and doesn't have a course that can't be taken since its prereq can't be taken etc, etc...
I want to know if by using a throw in the visit method is good practice. Since if we found a cycle in the graph, I can just throw. Now does the throw totally ignore the stack and goes straight down until it finds a catch. If so, does that mean, instead of implementing visit method to return false when a cycle is found. It would be faster to just throw instead of returning false all the way down the stack? Is this good practice for production level code. or is the return bool method better?
class Solution {
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<list<int>> vMap(numCourses);
vector<bool> globalVisited(numCourses, false);
for (auto it : prerequisites){
vMap[it.first].push_back(it.second);
}
try {
for (int i=0; i<numCourses; i++){
if (globalVisited[i] != true){
vector<bool> localVisited(numCourses, false);
visit(vMap, globalVisited, localVisited, i);
}
}
}
catch (...){
return false;
}
return true;
}
void visit(vector<list<int>>& vMap, vector<bool>& globalVisited, vector<bool>& localVisited, int i){
if (globalVisited[i] == true){ //reached a deadend, try a different node
return;
}
else if (localVisited[i] == true){ //found a cycle
throw new exception;
}
localVisited[i] = true;
for (auto it : vMap[i]){
visit(vMap, globalVisited, localVisited, it);
}
globalVisited[i] = true;
}
};

Related

C++ runtime error: addition of unsigned offset?

I wrote the following to check if text is palindrome, I run it on leetcode and I am getting errors:
class Solution {
public:
bool isPalindrome(string s) {
int l=0,r=s.length()-1;
while(l<r)
{
while (!isalpha(s[r]))
{
--r;
}
while (!isalpha(s[l]))
{
++l;
}
if (tolower(s[r])!=tolower(s[l]))
return false;
--r;
++l;
}
return true;
}
};
Line 1061: Char 9: runtime error: addition of unsigned offset to
0x7ffc7cc10880 overflowed to 0x7ffc7cc1087f (basic_string.h) SUMMARY:
UndefinedBehaviorSanitizer: undefined-behavior
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/basic_string.h:1070:9
what's the problem with my code?
You're going out of bounds here:
while (!isalpha(s[r]))
and here
while (!isalpha(s[l]))
r can became negative and l can become >= s.length().
You should add some checks like
while (l < r && !isalpha(s[r]))
and
while (l < r && !isalpha(s[l]))
The same problem in this line
if (tolower(s[r])!=tolower(s[l]))
This should be
if (l < r && tolower(s[r])!=tolower(s[l]))
Different approach (C++20)
A different approach is to erase all non-alpha characters from s with
std::erase_if(s, [](char c) { return !isalpha(c); });
and remove the inner while loops.
I think you were very close to the solution. The pitfall here are that:
you are modifying the loop control variable more than once in the loop
(as consequence) you are using the loop control variable after changing their values without further checks.
The easy way to fix this kind of issue is to do one single action for every iteration. you can achieve this just using "else".
class Solution {
public:
bool isPalindrome(string s) {
int l=0,r=s.length()-1;
while(l<r)
{
if(!isalpha(s[r]))
{
--r;
}
else if(!isalpha(s[l]))
{
++l;
}
else if (tolower(s[r])!=tolower(s[l]))
{
return false;
}
else
{
--r;
++l;
}
}
return true;
}
};

'Find Cycle in Directed Graph' algorithm not working in a particular leetcode problem. Error-"AddressSanitizer:StackOverflow on a particular address"

Question link:
course schedule leetcode
The question clearly boils down to finding if there is a cycle. I saw the algorithm for that in Tushar Roy's youtube channel but I am struggling to implement it. His idea was if I encounter an element already present in the stack (of nodes being explored) then there is a cycle. His implementation was in Java.
His solution:
CycleInDirectedGraph.java
class Solution {
public:
bool canFinish(int n, vector<vector<int>>& prerequisites)
{
vector<vector<int>> adj(n,vector<int>());
for(auto x:prerequisites)
{
adj[x[1]].push_back(x[0]);
}
unordered_set<int> whiteset;
unordered_set<int> greyset;
unordered_set<int> blackset;
for(int i=0;i<n;i++)
{
whiteset.insert(i);
}
int c=0;
while(!whiteset.empty())
{
if(dfs(*whiteset.begin(), greyset, whiteset, blackset,adj)) {
c=1;
break;
}
}
if(c==1)
return false;
else
return true;
}
bool dfs(int x,unordered_set<int> &greyset,unordered_set<int> &whiteset,unordered_set<int> &blackset,vector<vector<int>> &adj)
{
changeset(x,whiteset,greyset);
for(auto y:adj[x])
{
if(blackset.find(y)!=blackset.end())
continue;
if(greyset.find(y)!=greyset.end())
return true;
if(dfs(x,greyset,whiteset,blackset,adj))
return true;
}
changeset(x,greyset,blackset);
return false;
}
void changeset(int x,unordered_set<int> &a,unordered_set<int> &b)
{
a.erase(x);
b.insert(x);
}
};

How to delete elements from two lists upon contact?

I'm having an incredibly difficult time programming Space Invaders for a class. I am supposed to use a list to store my "missiles" and a list to store my "aliens" as well. I press space bar to load in a new alien, and when the two contact, I am attempting to delete both of them, and I can't even get past deleting the "alien". I get a variety of bugs when more than one missile is fired, and the missiles work fine if this function is commented out. I am forced to pass a list of missiles into another class that already contains a list of aliens and delete both.
Here is the offending code:
bool AlienMgr::checkHit(PlayerMgr& playerMgr)
{
bool hit = false; // If the player hits an alien, switches to true and is returned.
list<Missile*>::iterator missileIter;
list<Missile*> missileList = playerMgr.getMissiles();
int missileCount;
FloatRect missileBounds;
FloatRect alienBounds;
iter = myAliens.begin();
while (!myAliens.empty() && iter != myAliens.end())
{
alienBounds = (*iter)->getGlobalBounds();
if (!missileList.empty() && !hit)
{
for (missileIter = missileList.begin(); missileIter != missileList.end() && !hit; missileIter++)
{
missileBounds = (*missileIter)->getMissileBounds();
if (alienBounds.intersects(missileBounds))
{
delete (*iter);
iter = myAliens.erase(iter);
cout << "HIT" << endl;
}
else
{
iter++;
}
}
}
else
{
iter++;
}
}
return hit;
}
You have several problems in your code. I've tried to clean them up. Also, I hope you can use c++ 11.
bool AlienMgr::checkHit(PlayerMgr& playerMgr)
{
bool hit = false; // If the player hits an alien, switches to true and is returned.
list<Missile*> missileList = playerMgr.getMissiles();
int missileCount;
FloatRect missileBounds;
FloatRect alienBounds;
// iter == myAliens.end() if it's empty
for (auto iter = myAliens.begin(); iter != myAliens.end();)
{
bool hitDetected = false;
alienBounds = (*iter)->getGlobalBounds();
// remove all missiles intersecting current alien and set flag
missileList.remove_if([&](Missile* missile)
{
if (!alienBounds.intersects(missile->getMissileBounds()))
return false;
hitDetected = true;
delete missile;
return true;
});
if (hitDetected)
{
hit = true;
delete (*iter);
iter = myAliens.erase(iter);
cout << "HIT" << endl;
else
{
iter++;
}
}
return hit;
}
However, there are more critical problems. Your code is too c++98'ish.
I would advise several improvements:
Use std::vector instead of std::list (it's really hard to find case when list will be faster)
Use smart pointers instead of manual memory management (code would be much simple and easier to understand)

How to reset a static vector inside a function?

I am trying to solve a certain problem on an online judge using the Dynamic Programming paradigm. I have written a function which memoizes the results of smaller subproblems. But this function will be called t times in a single run. So when the function calls itself I want its "Memory" to be preserved, but when it is called from the driver I wan't the vector to be reset. How do I do that? I think having a global vector and reseting it after each call from the driver is possible, but as I have learnt from books and stack overflow that is "bad programming style". So what is a good sollution to this problem? Heres the code :
class mem{
public:
bool mike_win;
bool written;
};
bool calc(int a){
static vector<mem> memory(a);
if( a == 1){
return false;
}
if(memory[a-1].written == true){
return (!(memory[a-1].mike_win))
}
vector<int> div_list = divis(a);
//^^ divis is a function which takes a number and returns
//all its divisors in descending order in a vector<int>
for(vector<int>::iterator i = div_list.begin();i != div_list.end();i++){
if ( ! ( calc( a / (*i) ))){
memory[a-1].written = true;
memory[a-1].mike_win = true;
return true;
}
}
if(calc(a-1 ) == false){
memory[a-1].written = true;
memory[a-1].mike_win = true;
return true;
}
else{
memory[a-1].written = false;
memory[a-1].mike_win = false;
return false;
}
}
Heres a link to the question. And heres the function divis :
vector<int> divis(int a){
vector<int> div_list(int a )
if(a==2){
return div_list;
}
int k = sqrt(a);
for(int i=2;i<=k;i++){
if(!(a%i)){
div_list.push_back(i);
div_list.push_back(a/i);
}
}
sort(div_list.rbegin(),div_list.rend());
div_list.erase(unique(div_list.begin(),div_list.end()),div_list.end());
return div_list;
}
I think the way I would do it is to create two overloads of calc: on that takes just int as a parameter, and another that takes an int and a reference to vector<int>. That way, a user will call the first overload, which will create the temporary vector for memorization, and pass it to the second function, which passes the reference upon recursion. Kinda like this:
bool calc(int a, vector<int>& memory)
{
// Do your stuff here
// Instead of calling it as calc( a / (*i) ), just call
// it as calc( a / (*i) , memory )
}
bool calc(int a)
{
vector<int> memory(a);
calc(a, memory);
}
That way, you avoid having to do any sort of book-keeping in the heart of your algorithm to determine whether to clear the vector or not; it will be done automatically after the first call returns.

How to pass additional array to Thrust's min_element predicate

I'm trying to use Thrust's min_element reduction to find next edge in Prim's algorithm. I iterate over graph edges. This is my comparison function:
struct compareEdge {
__host__ /*__device__*/ bool operator()(Edge l, Edge r) {
if (visited[l.u] != visited[l.v] && visited[r.u] != visited[r.v]) {
return l.cost < r.cost;
} else if (visited[l.u] != visited[l.v]) {
return true;
} else {
return false;
}
}
};
Unfortunately this code cannot run on device, because I use visited array, where I mark already visited nodes. How can I pass this array to my predicate to make it usable from device-executed code?
There are probably a number of ways this can be handled. I will present one approach. Please note that your question is how to pass an arbitrary data set to a functor, which is what I'm trying to show. I'm not trying to address the question of whether or not your proposed functor is a useful comparison predicate for thrust::min_element (which I'm not sure of).
One approach is simply to have a statically defined array:
__device__ int d_visited[DSIZE];
then in your host code, before using the functor, you will need to initialize the array:
cudaMemcpyToSymbol(d_visited, visited, DSIZE*sizeof(int));
Your functor code would have to be modified. Since you may want the functor to be usable either on the host or the device, we will need to control the code based on this:
struct compareEdge {
__host__ __device__ bool operator()(Edge l, Edge r) {
#ifdef __CUDA_ARCH__
if (d_visited[l.u] != d_visited[l.v] && d_visited[r.u] != d_visited[r.v]) {
return l.cost < r.cost;
} else if (d_visited[l.u] != d_visited[l.v]) {
return true;
} else {
return false;
}
#else
if (visited[l.u] != visited[l.v] && visited[r.u] != visited[r.v]) {
return l.cost < r.cost;
} else if (visited[l.u] != visited[l.v]) {
return true;
} else {
return false;
}
#endif
}
};