Let's say I have this as current code:
if (GetFlag(...)) {
if (auto x = GetX(...)) {
if (auto y = GetY(...)) {
...
}
}
}
and that the method calls and variable definitions need to be made in this order for both correctness and performance reasons (we don't want to calculate x if GetFlag(...) returns false, and we don't want to calculate y if x is nullptr).
Is there a way to refactor this into a "one-liner"? The closest I got to actually compiling would be
if (auto x = GetX(...); auto x = GetX(...) && GetFlag(...)) { ... }
but this does not preserve the order of operations.
Thanks!
You can extract the conditionals into a separate function that returns a tuple, and structured bind in the if
std::tuple<bool, std::optional<X>, std::optional<Y>> getFlagsXY()
{
if (!getFlags())
{
return { false };
}
if (auto x = getX(); !x)
{
return { true, std::move(x) };
}
else
{
return { true, std::move(x), getY() };
}
}
if (auto [f, x, y] = getFlagsXY(); f && *x && *y) { ... }
And yes it is possible.
If statements stop processing terms once they see which branch is going to be taken. Try changing the values of GetFlag, GetX to see when the body of the if gets called.
#include <iostream>
bool GetFlag()
{
std::cout << "GetFlag\n";
return true;
}
int GetX()
{
std::cout << "GetX\n";
return 0;
}
int GetY()
{
std::cout << "GetY\n";
return 3;
}
int main()
{
int x;
int y;
if (GetFlag() && (x = GetX()) && (y = GetY()))
{
std::cout << "Do " << x << ", " << y;
}
return 0;
}
Related
I am running into infinite loop even after including errata changes in Skiena's dfs implementation from "The Algorithm Design Manual" book by Steven Skiena 2nd edition and I'd like to know how to fix it.
The reason seems quite obvious and applies to any undirected graph which makes me think may be I am doing it wrong but just cant figure out.
Take any undirected graph (or the one on pg171 if you have the book), say there is an edge (1,6). In the adjacency list alist[6] will have a node for 1 and alist[1] will have node for 6. Starting DFS for vertex = 1 (calling dfs(1)), it first discovers 6 and sets parent[6]=1. Recursive call dfs(6) then wants to discover 1 but 1 is already discovered. This causes first if condition in the while loop to become false
if (!discovered[y]) )
and therefore does not set parent[1].
1 is not processed yet and parent[6] is 1 (i-e y) as set in previous iteration therefore else if condition in the while loop is also false.
else if (((!processed[y]) && (parents[v] != y)) || (directed))
Since we do not reset the pointer p to the next node in the linked list because of else conditiona going false, it goes in an infinite loop
while (p != nullptr)
So basically it gets stuck at processing the first edge (1,6) and (6,1) and this should happen with any undirected graph. What is the fix for this infinite loop? or I am doing something wrong here different than skiena implementation?
Heres the minimum compilable and runnable code reproducing the infinite loop, including the main()
#include <iostream>
#include <queue>
const int MAX_VERTICES = 10000;
struct EdgeNode {
private:
int y{ -1 };
EdgeNode* next{ nullptr };
public:
EdgeNode(int _y, EdgeNode* _next) : y{ _y }, next{ _next }{}
EdgeNode(int _y) : y{ _y }, next{ nullptr}{}
const int getY() const { return y; } ;
const EdgeNode* const getNext() const { return next; };
};
class Graph {
EdgeNode* edges[MAX_VERTICES]{ nullptr };
int degree[MAX_VERTICES]{ 0 };
int totalVertices{ 0 };
int totalEdges{ 0 };
bool directed{ false };
bool processed[MAX_VERTICES]{ false };
bool discovered[MAX_VERTICES]{ false };
bool finished = false;
int parents[MAX_VERTICES];
void initializeSearch() {
for (int i = 0; i < MAX_VERTICES; i++)
{
parents[i] = -1;
processed[i] = false;
discovered[i] = false;
}
finished = false;
}
public:
int Vertices() const {return totalVertices; }
int Edges() const { return totalEdges; }
const EdgeNode* getEdge(int x) const {
if (x > MAX_VERTICES) return nullptr;
return edges[x];
}
bool insertEdge(int x, int y) { return insertEdge(x, y, false); }
bool insertEdge(int x, int y, bool _directed) {
if (x > MAX_VERTICES) { std::cout << std::endl << "Unable to insert edge. Max vertices allowed:" << MAX_VERTICES; return false; }
EdgeNode* temp = new EdgeNode(y, edges[x]);
if (degree[x] == 0) totalVertices++;
edges[x] = temp;
degree[x]++;
totalEdges++;
if (!_directed) {
insertEdge(y, x, true);
}
return true;
}
void process_vertex_late(int vertex) {}
void process_vertex_early(int vertex) {std::cout << std::endl << "Processing Vertex: " << vertex;}
void process_edge_dfs(int x, int y) {
std::cout << std::endl << "\tProcessing Edge(" << x << "," << y << ")";
if (discovered[y] && (parents[x] != y)) {
std::cout << std::endl << "Cycle(" << x << "," << y << ")";
std::cout << std::endl << std::endl;
finished = true;
}
}
void dfs1(int start) {
initializeSearch();
dfs(start, false);
}
void dfs(int v, bool print) {
const EdgeNode* p;
int y;
if (finished)
return;
discovered[v] = true;
process_vertex_early(v);
p = getEdge(v);
while (p != nullptr) {
y = p->getY();
if (!discovered[y]) {
parents[y] = v;
process_edge_dfs(v, y);
dfs(y, false);
}
else if (((!processed[y]) && (parents[v] != y)) || (directed))
{
process_edge_dfs(v, y);
if (finished)
return;
p = p->getNext();
}
}
process_vertex_late(v);
processed[v] = true;
}
};
int main()
{
Graph graph;
graph.insertEdge(1, 2);
graph.insertEdge(1, 5);
graph.insertEdge(1, 6);
graph.insertEdge(2, 5);
graph.insertEdge(2, 3);
graph.insertEdge(3, 4);
graph.insertEdge(4, 5);
graph.dfs1(1);
return 0;
}
I hope you find your answer.
I have the second edition of the book and I see what is your mistake.
You wrote
else if (((!processed[y]) && (parents[v] != y)) || (directed))
{
process_edge_dfs(v, y);
if (finished)
return;
p = p->getNext();
}
The correct implementation is :
else if (((!processed[y]) && (parents[v] != y)) || (directed))
process_edge_dfs(v, y);
if (finished) return;
p = p->getNext();
...
In my edition, the code is on two pages and the alignment is not the same.
it's very confusing.
Im pretty new to C++ and I have problem with pointers. Can someone please explain me how does this code return 0 for y, instead of 20?
#include <iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
Test setX(int a) { x = a; cout << "hello"; return *this; }
Test setY(int b) { y = b; cout << "world"; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1;
obj1.setX(10).setY(20);
obj1.print();
return 0;
}
}
Your methods are returning copies of the test object.
Test setX(int a) { x = a; cout << "hello"; return *this; }
Test setY(int b) { y = b; cout << "world"; return *this; }
So obj1.setX(10) applies to the original, but then .SetY(20) applies to the copy.
You need to return by reference:
Test& setX(int a) { x = a; cout << "hello"; return *this; }
Test& setY(int b) { y = b; cout << "world"; return *this; }
You are trying to implement a design called "function chaining". To do this, you must return a reference to the current object, not a brand new object:
Test& setX(int a) { x = a; cout << "hello"; return *this; }
Test& setY(int b) { y = b; cout << "world"; return *this; }
Since you are returning the current object, this will now work. Your example was returning a brand new Test object, which is why you were seeing 0 as the output.
If you want to chain calls to Test, your setters need to return a reference on Test instance.
If you do not return a reference to the object, it is not udpated, a copy of it is updated.
Without the reference what you wrote is equivalent to:
Test tmp = obj1.setX(10);
tmp.setY(20)
obj1.print()
(tmp is a "local" variable created by the compiler)
Fixed code below:
#include <iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
Test &setX(int a) { x = a; cout << "hello"; return *this; }
Test &setY(int b) { y = b; cout << "world"; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1;
obj1.setX(10).setY(20);
obj1.print();
return 0;
}
How to make a function that calls the next prime number every time I call it?
Here's what I've got:
#include <iostream>
#include <cmath>
void prime();
using namespace std;
int main()
{
void prime();
}
bool isPrime(int integer)
{
int x;
int br = 0;
for (x = 1; x < integer; x++) {
if (integer % x == 0) {
br++;
}
}
if (br == 1) {
cout << " The number " << integer << " is prime " << endl;
}
else if (br > 1) {
cout << " The number " << integer << " is not prime " << endl;
}
}
void prime(){
for (int x = 2;x<1000;x++){
isPrime(x);
}
}
Nothing is displayed when I run it.
Edit: Here I added the main function...
int main()
{
void prime();
}
void prime(); is a function declaration. It has no effect; the function is not called. You must call the function:
int main()
{
prime();
}
And then there's another big problem. Your isPrime function doesn't return anything. Add a return statement to it:
return br == 1;
If you do not intend for the function to return anything (and your code currently doesn't use the returned value, so this may indeed be your intention), then make it a void function.
isPrime is boolean function is expecting to return true or false, there is no return in your code. Make it a void if you just want to "cout" the number on the console.
The main issue with your code is that you are not returning anything from your isPrime function (which should give back a boolean value).
For that you can rewrite your code as:
bool is_prime(int integer) {
if (integer < 2) return true;
auto range = boost::irange(2, integer);
auto pred = [integer](auto i) { return integer % i == 0; };
return find_if(range, pred) == std::end(range);
}
Live demo
Second, your main:
int main()
{
void prime();
}
Is really just declaring the function prime. In order to call it you can write:
void prime();
int main() {
prime();
}
const int PIXEL_WIDTH = 10;
const int PIXEL_HEIGHT = 10;
const int WORLD_X = 64; //WORLD_X * PIXEL WIDTH = SCREEN_WIDTH if you want the world to be the same size as the screen
const int WORLD_Y = 64;
enum Pixel_Types {
AIR,
WALL,
DIRT,
STONE
};
class Pixel
{
int x, y;
bool affected_by_gravity;
Pixel_Types type;
public:
Pixel() : affected_by_gravity(false), type(AIR), x(0), y(0) {}
Pixel(int temp_x, int temp_y) : affected_by_gravity(false), type(AIR), x(temp_x), y(temp_y) {}
int getX() { return x; } //x is 0-63, scales up in the rendering code
int getY() { return y; } //y is 0-63, scales up in the rendering code
int getScreenX() { return x*PIXEL_WIDTH; } //x is 0-63, scales up in the rendering code
int getScreenY() { return y*PIXEL_HEIGHT; } //y is 0-63, scales up in the rendering code
bool setDeltaX(int temp_delta_x);
bool setDeltaY(int temp_delta_y);
void setAffectedByGravity(bool yesorno) { affected_by_gravity = yesorno; }
bool getAffectedByGravity() { return affected_by_gravity; }
Pixel_Types getType() { return type; }
void setType(Pixel_Types what_type) { type = what_type; }//if (type == DIRT or type == STONE) { affected_by_gravity = true; } }
};
std::vector<Pixel> world; //the world is a dynamically allocated thing
Pixel* getPixelFromCoordinates(int x, int y)
{
if (x > 63) x = 63;
else if (x < 0) x = 0;
if (y > 63) y = 63;
else if (y < 0) y = 0;
for (int pixel_index = 0; pixel_index < world.size(); pixel_index++) {
if (world.at(pixel_index).getX() == x && world.at(pixel_index).getY() == y) {
return &world.at(pixel_index);
}
}
return NULL;
}
bool Pixel::setDeltaX(int temp_delta_x) {
if (x+temp_delta_x > SCREEN_WIDTH/PIXEL_WIDTH or x+temp_delta_x < 0) {
return false;
}
if (getPixelFromCoordinates(x+temp_delta_x, y)->type == AIR) {
x += temp_delta_x;
return true;
}
return false;
}
bool Pixel::setDeltaY(int temp_delta_y) {
if (y+temp_delta_y > SCREEN_HEIGHT/PIXEL_HEIGHT or y+temp_delta_y < 0) {
return false;
}
if (getPixelFromCoordinates(x, y+temp_delta_y)->type == AIR) {
y += temp_delta_y;
return true;
}
return false;
}
void generateWorld()
{
for (int world_generation_index = 0; world_generation_index < 4096; world_generation_index++) {
int x = world_generation_index % WORLD_X; //the world is 64 pixels left and right, and 64 up and down. this math is pretty easy and just extrapolates that. also each pixel is 10 pixels across, times 64 pixels = 640 (the resolution)
int y = floor(world_generation_index / WORLD_Y); //both x and y start at 0
world.push_back(Pixel(x, y));
if (x == 0 || x == 63) {
world.at(world_generation_index).setType(WALL);
}
if (y == 1) {
world.at(world_generation_index).setType(WALL);
}
}
std::cout << "World size: " << world.size() << std::endl;
}
void createPixel(int x, int y, Pixel_Types type)
{
std::cout << x << std::endl;
std::cout << y << std::endl << std::endl;
y = (SCREEN_HEIGHT / PIXEL_HEIGHT) - y; //compensate for the stupid inverted y in opengl
//if (getPixelFromCoordinates(x, y)->getType() == AIR) {
getPixelFromCoordinates(x, y)->setType(type);
//}
}
void physicsOneStep()
{
for (int pixel_index = 0; pixel_index < world.size(); pixel_index++) {
if (world.at(pixel_index).getType() == DIRT or world.at(pixel_index).getType() == STONE) {//if (world.at(pixel_index).getAffectedByGravity()) {
world.at(pixel_index).setDeltaY(-1);
//std::cout << world.at(pixel_index).getX() << std::endl;
//std::cout << world.at(pixel_index).getY() << std::endl << std::endl;
}
}
}
So when I try to run this code (part of a larger project) it occasionally gives me a Segfault on calling setType(DIRT) from within createPixel(). I know that the values provided to createPixel() are within the range that they are allowed to be (0 to 64). It seems to segfault if you click (which calls createPixel()) in the same spot twice. The line that the debugger says segfaults is
void setType(Pixel_Types what_type) { type = what_type; }
though, I've verified that the values that I have supplied to this are correct.
Since there is no dynamic allocation inside the class, having a segfault on such an allocation most certainly occur because the this pointer itself is incorrect (NULL or badly allocated). You should get up the traceback when it segfaulted to see how the object on which you called setType was allocated. For example, shouldn't the line
world.push_back(Pixel(x, y));
be
world.push_back(new Pixel(x,y));
?
I'm trying to make a floodfill algorithm in C++, so my plan was to make an 2D array, and then each item would be an object, with property's to check for walls around it.
I note walls the following way,
1 = top
2 = right
4 = bottem
8 = left
so 13 would mean, top/bottem/left wall
but when i use std::bitset<sizeof(int)> bits(w); i get a "expected ';' before '(' token
How do i fix this? I've tried many things but it just won't work.
My code:
// een simpele floodfill
#include <stdlib.h>
#include <iostream>
#include <bitset>
class Hokjes {
int x;
int y;
int w;
public:
void setX(int i) { x = i; }
void setY(int i) { y = i; }
void setW(int i) { w = i; }
int getX() { return x; }
int getY() { return y; }
int getVal() { return x*y; }
std::bitset<sizeof(int)> bits(w); // error happens in this line
/* FreeSpace? */
bool Left() {
if (bits[3]) return false;
return true; }
bool Bottum() {
if (bits[2]) return false;
return true; }
bool Right() {
if (bits[1]) return false;
return true; }
bool Top() {
if (bits[0]) return false;
return true; }
};
int main() {
using namespace std;
int NrKamers;
std::cin >> NrKamers;
for (int i = 0; i<NrKamers; i++){
int SizeX;
int SizeY;
Hokjes veld[SizeY][SizeX];
std::cin >> SizeY >> SizeX;
for (int Yas = 0; Yas <= SizeY; Yas++){
for (int Xas = 0; Xas <= SizeX; Xas++){
veld[Yas][Xas].setW((Yas+1)*Xas)
veld[Yas][Xas].setX(Xas);
veld[Yas][Xas].setY(Yas);
std::cout << veld[Yas][Xas].Top() << std::endl;
}
}
std::cout << SizeY << " " << SizeX;
}
std::cout << NrKamers << std::endl;
system("pause");
return 0;
}
This will work:
std::bitset<sizeof(int)> bits;
You'll need to initialize it in constructor:
Hokjes::Hokjes() : bits(w) { }
You're not allowed to initialize member vars at declaration point. So just declare bits: std::bitset<sizeof(int)> bits;
Since it looks like you want to keep w and
bits in sync just do bits = i;
in the SetW method (or even loose
the w member altogether and work
directly on bits).