This problem is from SPOJ. I was required to find whether the graph is Bi-partite or not. I'm using BFS to find it.
The problem here is in a while loop under the section //PROBLEM COMING HERE (please see the code under to find this statement.)
Problem description:
I want to toggle between 0 and 1. So I have chosen a bool value called flag and initialised it with 0. Now, per iteration I want to toggle it's value. So I have used flag = !flag. However, for some unknown reasons the flag value automatically toggles after the first iteration before executing the statement flag = ! flag.
So, because of this lot of problems are coming.
//BUG LIFE
#include <cstdio>
#include <vector>
#include <queue>
#define DEFAULT 2
using namespace std;
int main()
{
int t,n,e;
bool eflag;
//freopen("input.txt", "r", stdin);
//Taking the Testcase
scanf("%d",&t);
//Iterating each Testcase
for(int itr=1; itr<=t; itr++)
{
//n is the number of nodes in the graph and e is the no of edges.
scanf("%d %d",&n,&e);
//eflag is exit flag in short. this is used to early exit to save time if we already found out that the given graph isn't bi-partite.
//Assuming the graph is bi-partite hence eflag = false meaning no exit is required yet.
eflag = false;
//Graph data structure vector 2D Array
vector < vector < int > > graph(n+1);
//Taking edges as input and adding in the graph
for(int i = 1; i <=e; i++)
{
int v1,v2;
scanf("%d %d",&v1,&v2);
graph[v1].push_back(v2);
graph[v2].push_back(v1);
}
//Check the graph is bi-partite or not
//vis is an array which will hold whether a node has been explored or not. label is an array which segregates all the nodes in two groups 0 or 1.
bool vis[n+1]; int label[n+1];
//Initialising vis and label.
for(int i=1; i<=n; i++)
{
vis[i] = 0;
//DEFALUT VALUE IS 2. This is to tell that label of the node i hasn't been given yet or in otherwords, it's not be put in a group yet.
label[i] = DEFAULT;
}
//Taking nodes one by one and doing a BFS on it.
//LOGIC Here is: Take a node assign it a label 0 and add all the children of it in the queue and give them label 1. Now explore all children and give their children label 0. So like this, we alternate between labels.
//Now if we see that a node already has a label apart from 2 and a children is trying to label it with something different label it will mean that specific node is involved in both the groups. Hence we will set the eflag as true.
for(int i=1; i<=n && !eflag; i++)
{
if(!graph[i].empty() && !vis[i])
{
//Initialising the queue and adding the first node which has children.
queue <int> q;
q.push(i); bool flag;
//PROBLEM COMING HERE
//Assigning the label for this node as 0. meaning group 0
label[i] = 0; flag = false;
//BFS Starts
while(!q.empty() && !eflag)
{
int x = q.front(); q.pop();
printf("%d **\n",flag);
//The children of this node needs to have different label than parent. Hence flag = !flag
flag = !flag;
printf("%d %d\n",x,flag);
if(vis[x]) continue;
vis[x] = 1;
//Exploring the children and assigning them labels
for(vector <int>::iterator it = graph[x].begin(); it != graph[x].end(); it++)
{
//If the children doesn't have a default label and the label which it has is different than the one the parent is trying to put then it means that this child belongs to both the groups 0 and 1. So exit.
if(label[*it] != DEFAULT && label[*it] != flag)
{
printf("%d %d %d %d\n",x,*it,label[*it],flag);
eflag = true;
break;
}
else
{
label[*it] = flag;
}
}
printf("asd %d **\n",flag);
}
//PROBLEM ENDS HERE
}
}
if(eflag == false)
printf("Scenario #%d:\nNo suspicious bugs found!\n",itr);
else
printf("Scenario #%d:\nSuspicious bugs found!\n",itr);
}
return 0;
}
OUTPUT:
0 **
1 1
asd 1 **
0 **
2 1
2 1 0 1
asd 1 **
Scenario #1:
Suspicious bugs found!
Sample Input:
1
3 3
1 2
2 3
1 3
Your assumption in the comment:
After it prints asd 1** it should print again 1 ** because flag = ! flag hasn't been executed yet. However it shows 0 **
Is wrong. (Not the assumption that flag = ! flag hasn't been executed, that's correct.)
In the following snippet, I've cut most of the irrelevant code away (you're welcome). Let's name some of your loops:
for(int i=1; i<=n && !eflag; i++) // outer loop
{
// ..
queue <int> q;
q.push(i); bool flag;
label[i] = 0; flag = false; // (1)
while(!q.empty() && !eflag) // inner loop
{
int x = q.front(); q.pop();
printf("%d **\n",flag); // (2)
flag = !flag;
printf("%d %d\n",x,flag);
// ...
printf("asd %d **\n",flag); // (3)
}
// ...
}
You only ever push exactly one element into q. That's at the top of outer loop. You always pop it at the top of inner loop. Inner loops condition is true only if the queue is not empty. Therefore the inner loop always runs at most once per outer loop. Because the inner loop is never repeated more than once, you always jump to the beginning of the outer loop after printing asd 1** at the end of inner loop (3). At the top of outer loop (1), you assign flag = false. Therefore, regardless of the value of flag when it's printed at (3), it's value will always be false at (2).
As you can see, the variable isn't changing "automatically" or because of "unknown reasons". It's changing because you assign it at (1).
Related
I'm trying to compare two decks of cards, yet every time I try another method of doing it, I get the same result... Everything before the code outputs, and it just freezes as soon as it hits the comparison code, as if it's stuck in an infinite loop.
I've tried for loops, static variables, do-while loops, etc. This is my first time leaving the loop at the client code.
The code that supposedly throws the program into an infinite loop.
while (repeatLoop == false)
{
deck1.shuffleDeck();
counter++;
repeatLoop = deck1.compareDecks();
}
compareDecks function.
bool deck::compareDecks()
{
int deckCount = 0;
suitType tempOriginalSuit;
suitType tempShuffleSuit;
rankType tempOriginalRank;
rankType tempShuffleRank;
while (index < 52)
{
tempOriginalSuit = originalCardDeck[index].getSuit();
tempShuffleSuit = shuffledCardDeck[index].getSuit();
if (int(tempOriginalSuit) == int(tempShuffleSuit))
{
tempOriginalRank = originalCardDeck[index].getRank();
tempShuffleRank = shuffledCardDeck[index].getRank();
if (int(tempOriginalRank) == int(tempShuffleRank))
{
deckCount++;
if (deckCount == 52)
return true;
}
}
else
{
return false;
index++;
}
}
}
The shuffleDeck function
(This function pushes back the first card from the first half of the deck and the first card from the second half of the deck towards the end until all 52 cards have been pushed in this pattern. This makes the deck have 52 x 2 cards (with the second half of the deck being the perfect shuffle), so I delete the first half of the cards using .erase as it is not needed)
void deck::shuffleDeck()
{
for (int a = 0, b = 2; a < 2 && b < 4; a++, b++)
{
for (int i = 2; i < 15; i++)
{
shuffledCardDeck.push_back(card{ static_cast<cardSpace::suitType>(a),
static_cast<cardSpace::rankType>(i) });
shuffledCardDeck.push_back(card{ static_cast<cardSpace::suitType>(b),
static_cast<cardSpace::rankType>(i) });
}
}
shuffledCardDeck.erase(shuffledCardDeck.begin(),
shuffledCardDeck.begin() + (shuffledCardDeck.size() / 2));
}
The two decks initialized by this constructor.
deck::deck()
{
for (int i = 0; i < 4; i++)
{
for (int j = 2; j < 15; j++)
{
originalCardDeck.push_back(card{ static_cast<cardSpace::suitType>(i),
static_cast<cardSpace::rankType>(j) });
shuffledCardDeck.push_back(card{ static_cast<cardSpace::suitType>(i),
static_cast<cardSpace::rankType>(j) });
}
}
}
Also note that I've done a perfect shuffle on the shuffledCardDeck vector in another function. I'm trying to repeat the perfectShuffle function until it reaches it's original state and output how many times it took to do this.
I get an infinite loop.
EDIT: I've decided to add the return false; statement in the compareDecks function into the if-else. Also, I think what's causing the problem is that my index i is reset to zero everytime it is called again. Are there any solutions you guys could propose to this? I've tried using static variables, but they just would not increment in the for loop.
EDIT 2: I enclosed my if statements within the curly braces, per users' request, as it's a flaw in my code.
EDIT 3: After commenting out
deck1.shuffleDeck()
The compareDecks function returned true, stating that the decks are equal, which isn't supposed to happen... This caused the loop to end after only one loop.
I was expecting you to actually shuffle the deck.
Your code was pushing a specific, newly synthesized card onto the end of the deck:
shuffledCardDeck.push_back(card{ static_cast<cardSpace::suitType>(a),
static_cast<cardSpace::rankType>(i) });
For example, the first card it will push is always the 2 of 0's (Whatever the 0th suit is). That's not what you want. You actually want to push a copy of the card that is at a specific position index in the deck. For example, loop index from 0 to 25 and then push shuffledCardDeck[index] and shuffledCardDeck[26 + index].
Then you can still wrap up by using your technique of erasing the first half of the deck.
void deck::shuffleDeck()
{
for (int index = 0; index < 26; ++index) {
shuffledCardDeck.push_back(shuffledCardDeck[index]);
shuffledCardDeck.push_back(shuffledCardDeck[26 + index]);
}
shuffledCardDeck.erase(shuffledCardDeck.begin(),
shuffledCardDeck.begin() + 52);
}
You are not modifying the value in the loop, you're using a double equals sign:
repeatLoop == deck1.compareDecks();
That would explain your observed behavior.
ArrayBag foundBag;
int z;
z = getCurrentSize(); // tell you have many items exit in the bag
for (int i = 0; i < z; i++ )
{
int cur = items[i]; //cur is use to hold each number in the vector and items is the first list of number.
bool found = false; // start as false so it doesnt trigger the true right away
for (int j = 0; j < foundBag.getCurrentSize(); j++) // this loop check the number currently inside cur agianst everything in the foundbag at the moment
{
if (foundBag.items[i] = cur)
{
found == true; // << it didnt detect that it have found the number. I think the problem is here
}
}
if (found == true)
{
// do nothing if found since number is already in the foundbag
}
else if (found != true)
{
foundBag.add(cur); // if number is not found in the foundBag add it to the found bag.
}
}
So what I m trying to do is comparing value from an existing list to a new empty one that is called foundBag in this case. So basically it suppose to get value from the first bag and then check if that number exit in the first bag or not then it will add that number to the foundBag if it did not find it. If it already found the number it will do nothing and move to the next element in the first bag.
say the first bag have number 3 4 5 7 5 8 it should add everything from 3 4 5 7 then do nothing when it get to the second 5 then add 8 to the foundBag.
at the end foundBag should contain: 3 4 5 7 8
The problem is it doesnt seem to correctly detect that the number is already in the foundBag so it add everything.
I been using the step-over function in visual studio to look at each step but I couldnt figure out why the bool still go to false when it found the identical number.
Im not very strong in english so if this doesnt make sense please ask for more explanation
Thank you
It looks like you have your = and == mixed up.
if (foundBag.items[j] == cur) // Use == here for comparison
{
found = true; // Use = here for assignment
}
By the way, if all you're doing is looking for an element in a collection, prefer an algorithm from the standard library:
auto result = std::count(std::begin(foundBag.items), std::end(foundBag.items), cur);
if (result == std::end(foundBag.items)) {
// Not found; Add it
foundBag.add(cur);
}
I want to write a program that randomly generates a tournament tree using only the number of challengers. I read into another such problem, but the answer described how ranks would take part and seeding the players, which went a little over head.
The problem I am facing is that my algorithm produces an infinite loop for values between 1 and 4 inclusively. For all values otherwise, the program runs as desired.
My approach was to take in an array of strings for the competitors' names. Then, I would iterate over each position and randomly select a competitor's name to take that spot. Because I am swapping the names, I have to check for duplicates in the array. I believe this is where my code is experiencing issues.
Here is the snippet that actually determines the tree
for(int i = 0; i < no_players;) {
int index = rand() % ((no_players - i) + i);
// randomly choose an element from the remainder
string temp = players[index];
bool unique = true;
// check all the elements before the current position
for(int j = 0; j < i; j++) {
// if the element is already there, it is not unique
if(players[j] == temp)
unique = false;
}
// only if the element is unique, perform the swap
if(unique) {
players[index] = players[i];
players[i] = temp;
i++;
}
}
Any help is much appreciated!
I've started learning C++ Sets and Iterators and I can't figure if I'm doing this correctly since I'm relatively new to programming.
I've created a Set of a struct with a custom comparator that puts the items in a decreasing order. Before receiving the input I don't know how many items my Set will contain. It can contain any number of items from 0 to 1000.
Here are the Setdefinitions:
typedef struct Pop {
int value_one; int node_value;
} Pop;
struct comparator {
bool operator() (const Pop& lhs, const Pop& rhs) const {
if (rhs.value_one == lhs.value_one) {
return lhs.node_value < rhs.node_value;
} else { return rhs.value_one < lhs.value_one;}
}
};
set<Pop, comparator> pop;
set<Pop>::iterator it;
And this is the algorithm. It should find a minimum value and print that value. If it does not find (the function do_some_work(...) returns 0), it should print "Zero work found!\n":
int minimum = (INT_MAX) / 2; int result;
int main(int argc, char** argv) {
//....
//After reading input and adding values to the SET gets to this part
Pop next;
Pop current;
for (it = pop.begin(); it != pop.end() && minimum != 1; it++) {
current = *it;
temp_it = it;
temp_it++;
if (temp_it != pop.end()) {
next = *temp_it;
// This function returns a integer value that can be any number from 0 to 5000.
// Besides this, it checks if the value found is less that the minimum (declared as global) and different of 0 and if so
// updates the minimum value. Even if the set as 1000 items and at the first iteration the value
// found is 1, minimum is updated with 1 and we should break out of the for loop.
result = do_some_work(current.node_value);
if (result > 0 && next.value_one < current.value_one) {
break;
}
} else {
result = do_some_work(current.node_value);
}
}
if (minimum != (INT_MAX) / 2) {
printf("%d\n", minimum);
} else {
printf("Zero work found!\n");
}
return 0;
}
Here are some possible outcomes.
If the Set is empty it should print Zero work found!
If the Set as one item and do_some_work(current.node_value) returns a value bigger than 0 it should printf("%d\n", minimum); or Zero work found! otherwise.
Imagine I have this Set (first position value_one and second position node_value:
4 2
3 6
3 7
3 8
3 10
2 34
If in the first iteration do_some_work(current.node_value) returns a value bigger than 0, since all other items value_one are smaller, it should break the loop, print the minimum and exit the program.
If in the first iteration do_some_work(current.node_value) returns 0, I advance in the Set and since there are 4 items with value_one as 3 I must analyze this 4 items because any of these can return a possible valid minimum value. If any of these updates the minimum value to 1, it should break the loop, print the minimum and exit the program.
In this case, the last item of the Set is only analysed if all other items return 0 or minimum value is set to 1.
For me this is both an algorithmic problem and a programming problem.
With this code, am I analysing all the possibilities and if minimum is 1, breaking the loop since if 1 is returned there's no need to check any other items?
I am attempting to write a method DFS method for a directed graph. Right now I am running into a segmentation fault, and I am really unsure as to where it is. From what I understand of directed graphs I believe that my logic is right... but a fresh set of eyes would be a very nice help.
Here is my function:
void wdigraph::depth_first (int v) const {
static int fVertex = -1;
static bool* visited = NULL;
if( fVertex == -1 ) {
fVertex = v;
visited = new bool[size];
for( int x = 0; x < size; x++ ) {
visited[x] = false;
}
}
cout << label[v];
visited[v] = true;
for (int v = 0; v < adj_matrix.size(); v++) {
for( int x = 0; x < adj_matrix.size(); x++) {
if( adj_matrix[v][x] != 0 && visited[x] != false ) {
cout << " -> ";
depth_first(x);
}
if ( v == fVertex ) {
fVertex = -1;
delete [] visited;
visited = NULL;
}
}
}
}
class definition:
class wdigraph {
public:
wdigraph(int =NO_NODES); // default constructor
~wdigraph() {}; // destructor
int get_size() { return size; } // returns size of digraph
void depth_first(int) const;// traverses graph using depth-first search
void print_graph() const; // prints adjacency matrix of digraph
private:
int size; // size of digraph
vector<char> label; // node labels
vector< vector<int> > adj_matrix; // adjacency matrix
};
thanks!
You are deleting visited before the end of the program.
Coming back to the starting vertex doesn't mean you finished.
For example, for the graph of V = {1,2,3}, E={(1,2),(2,1),(1,3)}.
Also, notice you are using v as the input parameter and also as the for-loop variable.
There are a few things you might want to consider. The first is that function level static variables are not usually a good idea, you can probably redesign and make those either regular variables (at the cost of extra allocations) or instance members and keep them alive.
The function assumes that the adjacency matrix is square, but the initialization code is not shown, so it should be checked. The assumption can be removed by making the inner loop condition adj_matrix[v].size() (given a node v) or else if that is an invariant, add an assert before that inner loop: assert( adj_matrix[v].size() == adj_matrix.size() && "adj_matrix is not square!" ); --the same goes for the member size and the size of the adj_matrix it self.
The whole algorithm seems more complex than it should, a DFS starting at node v has the general shape of:
dfs( v )
set visited[ v ]
operate on node (print node label...)
for each node reachable from v:
if not visited[ node ]:
dfs( node )
Your algorithm seems to be (incorrectly by the way) transversing the graph in the opposite direction. You set the given node as visited, and then try to locate any node that is the start point of an edge to that node. That is, instead of following nodes reachable from v, you are trying to get nodes for which v is reachable. If that is the case (i.e. if the objective is printing all paths that converge in v) then you must be careful not to hit the same edge twice or you will end up in an infinite loop -> stackoverflow.
To see that you will end with stackoverlow, consider this example. The start node is 1. You create the visited vector and mark position 1 as visited. You find that there is an edge (0,1) in the tree, and that triggers the if: adj_matrix[0][1] != 0 && visited[1], so you enter recursively with start node being 1 again. This time you don't construct the auxiliary data, but remark visited[1], enter the loop, find the same edge and call recursively...
I see a couple of problems:
The following line
if( adj_matrix[v][x] != 0 && visited[x] != false ) {
should be changed to
if( adj_matrix[v][x] != 0 && visited[x] == false ) {
(You want to recurse only on vertices that have not been visited already.)
Also, you're creating a new variable v in the for loop that hides the parameter v: that's legal C++, but it's almost always a terrible idea.