Given two bitset objects 'B1' and 'B2' of length 'n' respectively. Whats the efficient way to say whether all the bits that are set in 'B2' are also in 'B1'?
Example:
B1 = 110111
B2_bad = 011001
B2_good = 100001
So, 'B1' and 'B2_good' is good but not 'B1' and 'B2_bad'?
Well, I guess these two following methods might help. You might need to benchmark them as which is faster.
std::bitset<6> B1 (std::string("110111"));
std::bitset<6> B2_bad (std::string("011001"));
std::bitset<6> B2_good (std::string("100001"));
//////////////One way/////////////////////////
if ( (~B1 &= (B2_bad)).any()) std::cout << "No" << std::endl;
else std::cout << "Yes" << std::endl;
if ( (~B1 &= (B2_good)).any()) std::cout << "No" << std::endl;
else std::cout << "Yes" << std::endl;
///////////////Second way//////////////////
int i =0;
for (i = 0; i < B1.size(); ++i) if (B2_bad[i] == 1 && B1[i] == 0) break;
if (i == B1.size()) std::cout << "Yes" << std::endl;
else std::cout << "No" << std::endl;
for (i = 0; i < B1.size(); ++i) if (B2_good[i] == 1 && B1[i] == 0) break;
if (i == B1.size()) std::cout << "Yes" << std::endl;
else std::cout << "No" << std::endl;`
Probably, someone more proficient than me can comment on their performance. But my best guess is first method leverages the library functions which should give the best performance , however if most of your queries would have 'Result NO' and B1-B2 will not agree on one of the earlier bits then second method might have better runtime. As, library functions involved have a worst runtime complexity of O(n).
Related
The problem is a part of my computer science homework. The homework includes 5 different types of students that travel through a given weighted undirected node graph where each student has a different method. The fifth student is the most difficult one and I haven't been able to implement it efficiently.
The fifth student has a secret power, (s)he can teleport between adjacent nodes, so it takes 0 time to travel between them. However, to recharge that secret power, (s)he needs to pass two edges, and (s)he does not have that secret power at the beginning of his/her journey. Unlike other four students, (s)he can use the same edge multiple times, so in the first move, (s)he may go N_1->N_2 and N_2->N_1 to recharge his/her secret power. (S)he cannot store his/her secret power and must use it right away after after gaining it.
The fifth student wants to know the shortest time to reach the summit. At start, (s)he does not have any power, so (s)he needs to pass two edges to recharge it.
The method i tried was a modification of Dijkstra's Algorithm; where instead of moving node by node, from one node it calculates all three possible jumps, only considering the weights of the first two jumps. It considers all cases such as going to a node and coming back to recharge power and jump a highly weighted node. It does work and i do get all the correct answers for the given test cases, but it is SLOW. We are under a two second limit and right now my algorithm takes around 4 seconds for test cases with 50 000 nodes and 100 000 edges.
I'm guessing the problem is within reaching neighbors since there are 3 nested for loops to reach all possible 3 jump away neighbors (while also being able to use the same edges more than once), which basically makes this O(n^3) (But I'm not great with big-oh notation so I'm not sure if it's actually that.)
Does anyone have any ideas to make this algorithm more efficient, or a different algorithm that isn't so slow?
Any help is appreciated!
Here's the code if it's of any help.
long long int HelpStudents::fifthStudent() {
auto start = std::chrono::system_clock::now();
set< pair<long long int,int> >setds;
vector<long long int> dist(totalNodes+15,std::numeric_limits<long long int>::max());
setds.insert(make_pair(0,1));
dist[1] = 0;
bool change = false;
int counter = 0; //these variables were just for checking some things
int max_counter = 0;
int changed_summit = 0;
int operations_after_last_change = 0;
int w1;
int w2;
int db = 0;
vector<int> neighbors;
vector<int> neighbors2;
vector<int> neighbors3;
int u;
while(!setds.empty()){
pair<long long int,int> tmp = *(setds.begin());
setds.erase(setds.begin());
u = tmp.second; //vertex label
if(dist[u] > dist[summit_no]){
continue;
}
if(!change){
counter++;
}else{
counter = 0; //debugging stuff
}
db++;
//cout << db2 << endl;
operations_after_last_change++;
max_counter = max(counter,max_counter);
//cout << "counter: " << counter <<endl;
change = false;
neighbors = adjacency_map[u]; //adjacency map holds a vector which contains the adjacent nodes for the given key
//cout << "processing: " << "(" << tmp.first << ","<< tmp.second << ") " << endl;
for(int nb : neighbors){
w1 = getWeight(u,nb); //this is one jump,
//nb is neighboor
neighbors2 = adjacency_map[nb];
//cout << "\t->" << nb << endl;
if( nb == summit_no){
if(dist[nb] > dist[u] + (w1)){
auto t = setds.find(make_pair(dist[nb],nb));
if(t != setds.end()){
setds.erase(t);
}
dist[nb] = dist[u] + (w1);
change = true;
changed_summit++;
operations_after_last_change = 0;
//cout << "changed summit to " << (dist[u] + (w1)) << endl;
//continue;
}
}
for(int nb2: neighbors2){ //second jump
w2 = getWeight(nb,nb2);
//cout << "\t\t->" << nb2 << endl;
if( nb2 == summit_no){
if(dist[nb2] > dist[u] + (w1+w2)){
auto t = setds.find(make_pair(dist[nb2],nb2));
if(t != setds.end()){
setds.erase(t);
}
dist[nb2] = dist[u] + (w1+w2);
change=true;
changed_summit++;
operations_after_last_change = 0;
//cout << "changed summit to " << (dist[u] + (w1+w2)) << endl;
//continue;
}
}
neighbors3 = adjacency_map[nb2];
for(int nbf: neighbors3){ //third jump, no weight
//cout << "\t\t\t->" << nbf;
if(dist[nbf] > dist[u] + (w1+w2)){
auto t = setds.find(make_pair(dist[nbf],nbf));
if(t != setds.end()) {
setds.erase(t);
}
change = true;
dist[nbf] = dist[u] + (w1+w2);
if(nbf == summit_no){
changed_summit++;
operations_after_last_change = 0;
//cout << endl;
}else{
setds.insert(make_pair(dist[nbf],nbf));
//cout << "\t\t\t\t inserted ("<<dist[nbf]<<","<<nbf<<")" << endl;
}
//cout << "changed " << nbf << " to " << (dist[u] + (w1+w2)) << "; path: "<< u <<" -> "<<nb<<" -> "<<nb2 << " -> " <<nbf << endl;
//setds.insert(make_pair(dist[nbf],nbf));
}else{
//cout << endl;
}
}
}
}
}
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
cout << "time passed: "<< elapsed_seconds.count() <<" total loop: "<<db<< endl;
return dist[summit_no];
You make (or more likely imagine) a new directed graph with a node for each unique situation/state that student 5 can be in -- that is combination of original graph node and charge state (0, 1, or 2). Because there are 3 charge states, this graph will have 3 times as many nodes as the original.
Then you use perfectly ordinary Dijkstra's algorithm on this new graph.
I am trying to understand this programming problem whereby I am supposed to guess the data structures. I am having a slight issue with my program.
PROBLEM: I have no clue as to why my program always gets killed with signal 11 (segmentation fault) but it works and compiles fine.
About the program: n would be number of integer sets ; it takes in an integer p (command) and integer data and pushes/pops into the following data structures. I've use a bool as flag to check the statuses. Am I right to believe the structures would be destroyed after the while loop as it goes out of scope?
int main(){
int n;
while (cin >> n && n != 0){
stack<int> mystack;
queue<int> myqueue;
priority_queue<int> maxq;
bool isstack = true;
bool isqueue = true;
bool ispq = true;
for (int i = 0; i < n; i++){
int p, data;
cin >> p >> data;
if (p == 1){
if (isqueue) myqueue.push(data);
if (isstack) mystack.push(data);
if (ispq) maxq.push(data);
} else if (p == 2){
if ((mystack.empty() || mystack.top() != data) && isstack) isstack = false;
else mystack.pop();
if ((myqueue.empty() || myqueue.front() != data) && isqueue) isqueue = false;
else myqueue.pop();
if ((maxq.empty() || maxq.top() != data) && ispq) ispq = false;
else maxq.pop();
}
}
if (isstack && !(isqueue || ispq)) cout << "stack" << endl;
else if (isqueue && !(isstack || ispq)) cout << "queue" << endl;
else if (isstack && (ispq || isqueue) || (isqueue && ispq)) cout << "not sure" << endl;
else if (ispq && !(isstack || isqueue)) cout << "priority queue" << endl;
else cout << "impossible" << endl;
}
return 0;
}
Yes, the data structures you’ve used are local scope to while, so they get destructed at the end of while loop.
Unless you provide for what input you’re seeing segmentation fault, it’s hard to say. Or run it in debug mode, your program should break at line where seg fault occurs.
I tried to run this code.
This code threw an exception when you pop after 'isstack' was changed to false.
The exception was 'Expression: deque empty before pop'.
After the variable changed false, always condition statements are return false.
So you tried to pop at empty stack.
That is a just logical bug.
When I run it on the terminal it works fine but the loop. The for loop just doesn't do anything at all. I'm learning C++, so I don't know much.
#include <iostream>
#include <cstring>
using namespace std;
int main( int argc, char *argv[] ) {
if (argc == 2) {
cout << "The first argument is " << argv[0] << endl;
cout << "The second argument is " << argv[1] << endl;
} else if (argc > 2) {
cout << "Too many arguments" << endl;
exit(0);
} else {
cout << "Only one argument" << endl;
cout << "The argument is " << argv[0] << endl;
exit(0);
}
if (atoi(argv[1]) < 0) {
cout << "Error negative number" << endl;
exit(0);
}
// this loop does not work, everything else does.
for (int i = 1; i >= atoi(argv[1]); i++){
int count = atoi(argv[1]--);
cout << count << endl;
int sum = sum + i;
}
cout << "The sum is: " << endl;
return(0);}
I think that could be the if statements what are messing around with the loop.
I think you made mistake in the for loop.
You show use "<=" instead of ">=" in the for loop.
Hope this might helps you.
I guess your code is not reaching the for loop as you have exit() conditions on each and every condition of if. Your code only reaches the loop if you are passing 2 arguments in the terminal while you are running your code
So I'm trying to write a program that solves the "Dungeon Crawl" problem here: http://www.cplusplus.com/forum/articles/12974/. If you are too lazy to read the link (which is entirely understandable), the basic premise of the game is that a player moves on a 10x10 grid and tries to reach treasure while avoiding traps and moving enemies. Because everything is revealed to the player, it's not much of a real game, but I thought it'd be good coding practice. Sadly, I'm rusty on user input and never properly learned how to put an entire program together, which means I'm having serious problems with functions executing properly.
The main function is this:
int main()
{
int turn=0,enemyCount=0;
bool end=false;
srand (time(NULL));
node* world;
world = new node[100];
generateWorld(world);
drawWorld(world);
do {
playerMove(world);
enemiesMoves(world,enemyCount);
drawWorld(world);
end = endCheck(world);
turn++;
} while (end == false);
return 0;
}
I think this is fine as is, because it follows the simple process of gathering moves, updating the world, and then checking to see if an end condition has been reached. The problem is that numerous functions are not working as I would expect them to, and I can't figure out why they are not. This includes user input validation, updating the movement of the enemies, drawing the world, and checking if the game ended. I'll go in order.
This is the playerMove() function:
void playerMove(node* array){
int i,playerLocation,oldLocation;
bool valid=false;
char move;
for (i=0;i<100;i++){
if (array[i].player == true){
playerLocation = i;
oldLocation = playerLocation;
}
}
while(!valid){
if (cin >> move){
if (move=='w' || move=='s' || move=='a' || move=='d')
valid = true;
}
if (move=='w'){
playerLocation = oldLocation-10;
if (playerLocation < 0){
cout << "You can't swim." << endl;
valid = false;
}
}
else if (move=='s'){
playerLocation = oldLocation+10;
if (playerLocation > 99){
cout << "You can't swim." << endl;
valid = false;
}
}
else if (move=='a'){
playerLocation = oldLocation-1;
if (playerLocation % 10 == 9){
cout << "You can't swim." << endl;
valid = false;
}
}
else if (move=='d'){
playerLocation = oldLocation+1;
if (playerLocation % 10 == 0){
cout << "You can't swim." << endl;
valid = false;
}
}
}
array[oldLocation].player = false;
array[playerLocation].player = true;
}
It's supposed to gather player input, do nothing if the player enters a key that isn't WASD (they can only move in the four cardinal directions), reject an input if the player tries to move off the edge of the world, and update the player position. It does successfully do the latter, but it will not catch an invalid input, and if a move fails, it refuses to display the message it is supposed to.
This is the enemiesMoves function:
void enemiesMoves(node* array,int enemyCount){
int i,j=0,n,enemyLocations[enemyCount],oldLocations[enemyCount];
bool valid = false;
for (i=0;j<enemyCount;i++){
if (array[i].enemy==true){
enemyLocations[j] = i;
cout << enemyLocations[j] << endl;
j++;
}
}
for (j=0;j<enemyCount;j++){
oldLocations[j] = enemyLocations[j];
}
for (j=0;j<enemyCount;j++){
while (!valid){
n = rand() % 4 + 1;
if (n = 1){
enemyLocations[j] = oldLocations[j]-10;
if (enemyLocations[j] < 0)
valid = false;
}
else if (n = 2){
enemyLocations[j] = oldLocations[j]+10;
if (enemyLocations[j] > 100)
valid = false;
}
else if (n = 3){
enemyLocations[j] = oldLocations[j]-1;
if (enemyLocations[j] % 10 == 9)
valid = false;
}
else if (n = 1){
enemyLocations[j] = oldLocations[j]+1;
if (enemyLocations[j] % 10 == 0)
valid = false;
}
}
array[enemyLocations[j]].enemy = true;
array[oldLocations[j]].enemy = false;
}
}
It is supposed to move the enemies in a random direction, but reject the movement if the enemy moves off the world. Although I thought I properly copied over the playerMove() code to this, it refuses to update the position of the enemies; they stay in the same place turn after turn.
This is the drawWorld() function:
void drawWorld(node* array){
int i;
for (i=0;i<100;i++){
if (array[i].player==true)
cout << "P";
else if (array[i].trap==true)
cout << "T";
else if (array[i].enemy==true)
cout << "E";
else if (array[i].treasure==true)
cout << "X";
else if (array[i].player==true && array [i].treasure==true)
cout << "W";
else if ((array[i].player==true && array[i].trap==true) || (array[i].player==true && array[i].enemy==true))
cout << "L";
else {
cout << "O";
}
if ((i+1 % 10) == 0){
cout << endl;
}
}
cout << endl << endl;
}
It draws the world fine, except that it won't wrap the text every ten characters as it is plainly told to do. I can't fathom what I'm missing here.
Finally, this is the endCheck() function:
bool endCheck(node* array){
int i;
for (i=0;i<100;i++){
if (array[i].player==true && array[i].treasure==true){
cout << "You found the treasure and now enjoy a life of unmitigated opulence." << endl;
return true;
}
else if (array[i].player==true && array[i].trap==true){
cout << "You fell into a conspicuous trap and became tiger food." << endl;
return true;
}
else if (array[i].player==true && array[i].enemy==true){
cout << "You were captured alive by angry natives and enjoyed as part of their New Year's feast." << endl;
return true;
}
else
return false;
}
}
This is simply not executing at all. I can move the player onto a trap and nothing happens.
These problems are incredibly frustrating because I am simply unable to discern what is wrong with the code. I know the post is long, but if anyone could point out what's wrong it'd be greatly appreciated. Also it should be noted that I searched for answers before posting this, but because I think the problems are intrinsic to my code I was unable to find any usable answers.
You are returning at the end of first iteration. So it will check only first field and then return false (if there was no player and treasure/trap/enemy in first field).
Change your function to look like this:
bool endCheck(node* array){
int i;
for (i=0;i<100;i++){
if (array[i].player==true && array[i].treasure==true){
cout << "You found the treasure and now enjoy a life of unmitigated opulence." << endl;
return true;
}
else if (array[i].player==true && array[i].trap==true){
cout << "You fell into a conspicuous trap and became tiger food." << endl;
return true;
}
else if (array[i].player==true && array[i].enemy==true){
cout << "You were captured alive by angry natives and enjoyed as part of their New Year's feast." << endl;
return true;
}
}
return false;
}
You have to check all possible fields before returning false that indicates no collision.
In enemiesMoves(), you are checking if(n = 1), I'm sure you meant if(n == 1).
Do this:
....
n = rand() % 4 + 1;
if (n == 1){
.....
Also, n == 1 case is checked twice! Once in if and then in the last else if.
For the rand() function to actually generate random numbers on each run, initialize a random seed first using srand(), as follows:
/* initialize random seed: */
srand (time(NULL));
n = rand() % 4 + 1;
I'm detecting key pressing and have some problem with the detection with fn(function), ctrl(control), alt and fn(function).
I can detect space bar, enter, ESC, letters, numbers and the cursors. But i can't detect the special keys I tell before. Both method doesn't show anything on screen when I press these keys.
Method to detect normal keys
void KeyboardFunc(unsigned char key, int x, int y)
{
int numeros;
Key[key] = true;
cout << "-----------------" << endl;
cout << "PULSE " << (int) key << endl;
cout << "-----------------" << endl;
if(key >= 48 && key < 58)
{
numeros = key;
key = 'a';
}
switch ( key )
{
case ' ': // Space bar
cout << "Barra Espaciadora pulsada." << endl;
break;
case 13: // #13 es Enter
cout << "Enter pulsada." << endl;
break;
case 27: // "27" is the Escape key
cout << "Tecla ESC pulsada." << endl;
exit(1);
case 'a': // Teclado numérico.
cout << "Número pulsado: " << numeros - 48 << endl;
key = numeros;
}
}
Method to detect special keys:
void SpecialFunc(int key, int x, int y)
{
Arrow[key] = true;
cout << "-----------------" << endl;
cout << "ESPECIAL PULSADO: " << (int) key << endl;
cout << "-----------------" << endl;
switch ( key )
{
case GLUT_KEY_UP: // #73 es cursor arriba
cout << "Cursor ARRIBA pulsada." << endl;
break;
case GLUT_KEY_DOWN: // #81 es cursor abajo
cout << "Cursor ABAJO pulsada." << endl;
break;
case GLUT_KEY_LEFT: // #73 es cursor izquierda
cout << "Cursor IZQUIERDA pulsada." << endl;
break;
case GLUT_KEY_RIGHT: // #81 es cursor derecha
cout << "Cursor DERECHA pulsada." << endl;
break;
case 30: // #30 es alt_a
cout << "Tecla ALT pulsada." << endl;
break;
}
}
OpenGL does not deal with user input. It's a drawing API and only covers getting points, lines and triangles into a raster pixmap buffer.
What you are using right now is GLUT, a rather simple framework for small OpenGL demos. GLUT is not part of OpenGL! If GLUT no longer meets your demands it's time to go on using a more capable framework, or doing all the windowing and input processing from scratch.
You could switch to SDL - get a source for brutalchess,
http://brutalchess.sourceforge.net/
and see how keys are handled in it. datenwolf is right, opengl has nothing to do with input ( mouse, keys, window focus etc. ). You could also try SFML, it's simpler than SDL
http://rastergrid.com/blog/downloads/mountains-demo/
SDL is more flexible than SFML, e.g. KEY_PRESS is something different than KEY_RELEASE.
Ok so this post is old I know but I just happened to find it while looking for something else.
Answering anyway since it may help other people in the future.
GLUT actually supports the events of ALT... being pressed.
GLUT_ACTIVE_SHIFT – Set if either you press the SHIFT key, or Caps Lock is on. Note that if they are both on then the constant is not set.
GLUT_ACTIVE_CTRL – Set if you press the CTRL key.
GLUT_ACTIVE_ALT – Set if you press the ALT key.
All you have to do is:
void processNormalKeys(unsigned char key, int x, int y) {
if (key == 27)
exit(0);
else if (key=='r') {
int mod = glutGetModifiers();
if (mod == GLUT_ACTIVE_ALT)
//piece of code
else if(//...)
//piece of code
}}