How to prevent repeating long rvalue - c++

int main() {
int x = 1, y = 2, z = 3, w = 4;
#define formula x + y * z % w
x++;
do_something1(formula);
y++;
do_something2(formula);
z++;
do_something3(formula);
w++;
do_something4(formula);
#undef formula
return 0;
}
I'm currently using #define to prevent repeating long rvalue. Is there any better alternative way to do this?

Use lambda expression:
int main() {
int x = 1, y = 2, z = 3, w = 4;
auto formula = [&] { return x + y * z % w; };
x++;
do_something1(formula());
y++;
do_something2(formula());
z++;
do_something3(formula());
w++;
do_something4(formula());
return 0;
}

Related

How can I get the common digits of two int in C++? Example: (1234, 41567) --> 1 4

Given two int I want to get all the common digits and print out them separated by spaces.
So for example, if int x=1234; int y=41567; then I want to print out: 1 4.
This is my code. It does not work properly. When I run it, it prints 0 1 2 3 4 5 then stops.
I don't want to use vector nor arrays.
void problema3() {
int x, y, kX=0, kY=0;
cout << "x="; cin >> x;
cout << "y="; cin >> y;
int cx = x;
int cy = y;
for (int i = 0; i < 10; i++) {
kX = 0;
kY = 0;
x = cx;
y = cx;
while (x != 0 || kX==0) {
if (x % 10 == i) kX=1;
x /= 10;
}
while (y != 0 || kY == 0) {
if (y % 10 == i) kY=1;
y /= 10;
}
if (kX == 1 && kY == 1) cout << i << ' ';
}
}
int main()
{
problema3();
return 0;
}
If you're allowed to use std::set then you can do what you want as follows:
#include <iostream>
#include <set>
void print(int x, int y)
{
int individual_number1 = 0, individual_number2 = 0;
std::set<int> myset;
int savey = y;//this will be used to reset y when the 2nd do while loop finishes
do
{
individual_number1 = x % 10;
do
{
individual_number2 = y % 10;
if(individual_number1 == individual_number2)
{
myset.insert(individual_number1);
break;
}
y = y / 10;
}while( y > 0);
y = savey;
x = x / 10;
} while (x > 0);
//print out the element of the set
for(int i: myset)
{
std::cout<<i<<" ";
}
}
int main()
{
int x = 1234, y = 41567;
print(x, y);
return 0;
}
The output of the above program is as follows:
1 4
which can be seen here.
Your main bug is when assigning copies of cy.
//...
for (int i = 0; i < 10; i++) {
//...
x = cx;
y = cx; // <-- BUG! should read y = cy;
But that's not the only bug in your program.
Your digit detection logic is wrong. In particular, zero is not handled correctly, and since you did not put that reusable code in a function, your program is way more complex than it needs.
Here's the corrected logic for digit detection.
// checks if base 10 representation of a positive integer contains a certain digit (0-9)
bool hasDigit(int x, int d)
{
do
{
if (x % 10 == d)
return true;
x /= 10;
} while (x != 0);
return false;
}
Your main loop then becomes:
// assuming int x, y as inputs.
// ...
for (int i = 0; i < 10; ++i)
{
if (hasDigit(x, i) && hasDigit(y, i))
std::cout << i << ' ';
}
Which leaves very little room for bugs.
You can play with the code here: https://godbolt.org/z/5c5brEcEq

C++ std::vector with values from multiple classes

I'm using std::vector for storing my values into MyValues from my classes A and B. Inserted elements/values depends on the type of class. If it's A, inserts {x, y}, if B, inserts {x, y, z}. And I loop it, so i can try to add multiple values of it, to just test it. But when I loop A.ases 5 times and then B.bses 7 times, looped MyValues has 31 single elements for some reason. Is possible to add elements and "preserve forms" (If it's A -> {x, y}, if B, -> {x, y, z}), so I can get same values, like the ones I inserted and work with it?
classes:
std::vector<int> MyValues;
class A {
public:
short int x, y;
A() {
this->x = this->y = 0;
}
};
class B : public A{
public:
short int z;
B() {
this->z = 0;
}
};
main:
int main() {
A ases[5];
B bses[7];
for (short int a = 0; a < 5; a++) {
ases[a].x = 5 + a;
ases[a].y = 4 + a;
MyValues.insert(MyValues.end(), { ases[a].x, ases[a].y });
}
for (short int b = 0; b < 7; b++) {
bses[b].x = 2 + b;
bses[b].y = 3 + b;
bses[b].z = 1 + b;
MyValues.insert(MyValues.end(), { bses[b].x, bses[b].y, bses[b].z });
}
for (int v : MyValues) std::cout << "x y z = " << v << std::endl;
return 0;
}
output:
x y z = 5
x y z = 4
x y z = 6
x y z = 5
x y z = 7
x y z = 6
x y z = 8
x y z = 7
x y z = 9
x y z = 8
x y z = 2
x y z = 3
x y z = 1
x y z = 3
x y z = 4
x y z = 2
x y z = 4
x y z = 5
x y z = 3
x y z = 5
x y z = 6
x y z = 4
x y z = 6
x y z = 7
x y z = 5
x y z = 7
x y z = 8
x y z = 6
x y z = 8
x y z = 9
x y z = 7
If you are using visual studio 2019 then you should be able to turn on C++17. This demo uses std::optional. Not sure how efficient it is, but it's convenient.
#include <iostream>
#include <vector>
#include <optional>
struct Base
{
int x, y;
std::optional<int> z;
Base(int _x, int _y) :
x(_x),
y(_y)
{}
Base(int _x, int _y, int _z) :
x(_x),
y(_y),
z(_z)
{}
};
int main()
{
Base b1 {1, 2, 3};
Base b2 {4, 5};
Base b3 {9, 9, 9};
std::vector V {b1, b2, b3};
for (auto& item : V)
{
std::cout << item.x << " " << item.y << " ";
if (item.z.has_value())
std::cout << item.z.value();
std::cout << std::endl;
}
}
And for demo: https://godbolt.org/z/nbedjb
You could make your MyValues a vector of vectors, like this:
std::vector<std::vector<int>> MyValues;
Then, without changing the definitions of your A and B classes, you can insert 2- or 3-element vectors, using much the same code as you already have in your main function. You would only need to change the way you display the data; I have shown one way, in the code below, but there are many others, depending on how 'pretty' you want your output to be.
int main()
{
A ases[5];
B bses[7];
for (short int a = 0; a < 5; a++) {
ases[a].x = 5 + a;
ases[a].y = 4 + a;
MyValues.insert(MyValues.end(), { ases[a].x, ases[a].y });
}
for (short int b = 0; b < 7; b++) {
bses[b].x = 2 + b;
bses[b].y = 3 + b;
bses[b].z = 1 + b;
MyValues.insert(MyValues.end(), { bses[b].x, bses[b].y, bses[b].z });
}
// No change required up to here; just change the code for output...
for (auto v : MyValues) {
std::cout << "{ ";
bool first = true;
for (auto i : v) {
if (!first) std::cout << ", ";
std::cout << i;
first = false;
}
std::cout << " }" << std::endl;
}
return 0;
}
Output from above:
{ 5, 4 }
{ 6, 5 }
{ 7, 6 }
{ 8, 7 }
{ 9, 8 }
{ 2, 3, 1 }
{ 3, 4, 2 }
{ 4, 5, 3 }
{ 5, 6, 4 }
{ 6, 7, 5 }
{ 7, 8, 6 }
{ 8, 9, 7 }

terminated by signal SIGSEGV (Address boundary error) in recursive function

I'm trying to implement Karatsuba algorithm for multiplication. I'm kinda follow the pseudocode in this wiki page. But I'm always getting this error:
terminated by signal SIGSEGV (Address boundary error)
When I replaced the lines that cause the recursion to happen with something else:
z0 = multiply(a, c);
z1 = multiply(b, d);
z2 = multiply(a+b, c+d);
the error disappeared.
Here's my code:
#include <iostream>
#include <math.h>
long int multiply(int x, int y);
int get_length(int val);
int main()
{
int x = 0, y = 0;
long int result = 0;
std::cout << "Enter x: ";
std::cin >> x;
std::cout << "Enter y: ";
std::cin >> y;
result = multiply(x, y);
std::cout << "Result: " << result << std::endl;
return 0;
}
long int multiply(int x, int y)
{
if(x < 10 || y < 10) {
return x * y;
}
int x_len = get_length(x);
int y_len = get_length(y);
long int z0 = 0 , z1 = 0, z2 = 0;
int a = 0, b = 0, c = 0, d = 0;
a = x / pow(10, x_len);
b = x - (a * pow(10, x_len));
c = y / pow(10, y_len);
d = y - (c * pow(10, y_len));
z0 = multiply(a, c);
z1 = multiply(b, d);
z2 = multiply(a+b, c+d);
return (pow(10, x_len) * z0) + (pow(10, x_len/2) * (z2 - z1 - z0)) + z1;
}
int get_length(int val)
{
int count = 0;
while(val > 0) {
count++;
val /= 10;
}
return count;
}
I found the problem cause.
It was because of these lines:
a = x / pow(10, x_len);
b = x - (a * pow(10, x_len));
c = y / pow(10, y_len);
d = y - (c * pow(10, y_len));
It should be x_len / 2 instead of x_len and the same with y_len. Since it causes the recursion to be infinite.
You are using the pow function to do integer powers. It is not an integer function. Code your own pow function that's suitable for your application. For example:
int pow(int v, int q)
{
int ret = 1;
while (q > 1)
{
ret*=v;
q--;
}
return ret;
}
Make sure to put an int pow(int, int); at the top.

Swapping variables' values concisely using C++

How can I swap the values of two variables ?
This works, but I'd would prefer a one liner :
int a = 10, b = 30;
a = a + b;
b = a - b;
a = a - b;
Perhaps that's cheating but there's simply :
std::swap(a, b);
std::tie(x,y) = std::make_pair(y,x);
But std::swap(x,y) is much more readable and probably more efficient.
int main()
{
int x = 10, y = 10;
y = (x + y)-y;
}
Solved a little bit but not completely but solved if you use this code
int swap(int *x, int y){
*x = (*x + *y) - *x;
return 0;
}
int main()
{
int x = 10;
int y = 5;
y = (x + y) - y + swap(&x, &y);
cout << x << endl << y << endl;
}

C++ Rotation matrix issue when used on a square

I'm attempting to apply an a rotation matrix in C++ that rotates all points of square a specified degree around a specified origin. The catch is that it is based in the win32 console, so each point has to correspond with a pair of ints, rather than floating point values. As you can see below, the rotating square's overall shape is consistent with the desired result, but there are a number of 'holes' in it.
Here's my source code:
#include <iostream>
#include <cmath>
using namespace std;
enum {W = 50, H = 50, S = 25}; //Width, Height, Square size
struct Vector2i
{
int x;
int y;
Vector2i() {}
Vector2i(int _x, int _y) : x(_x), y(_y) {}
};
struct Square
{
bool Data[W][H];
Vector2i Origin = Vector2i(W / 2, H / 2);
void clear() {
for (int y = 0; y < H; ++y) {
for (int x = 0; x < W; ++x)
Data[x][y] = false;
}
}
void setSquare() {
for (int y = H / 2 - S / 2; y < H / 2 + S / 2; ++y) {
for (int x = W / 2 - S / 2; x < W / 2 + S / 2; ++x)
Data[x][y] = true;
}
}
void draw() {
for (int y = 0; y < H; ++y) {
for (int x = 0; x < W; ++x) {
if (y == Origin.y && x == Origin.x) std::cout << '+'; //Marks the origin
else if (Data[x][y]) std::cout << 'X';
else std::cout << '.';
}
std::cout << '\n';
}
}
};
Vector2i newPos(Vector2i old, double theta) {
theta *= 3.14159265d / 180.d; //Converting from degrees to radians
int X = ceil(cos(theta) * old.x - sin(theta) * old.y);
int Y = ceil(sin(theta) * old.x + cos(theta) * old.y);
return Vector2i(X, Y);
}
int main()
{
cout << "Enter an angle (in degrees): ";
double angle = 0;
cin >> angle;
Square One;
One.clear();
One.setSquare();
One.draw();
Square Two;
Two.clear();
///Draw the rotated square as the second square
for (int y = 0; y < H; ++y) {
for (int x = 0; x < W; ++x) {
if (One.Data[x][y]) {
Vector2i finalVec = newPos(Vector2i(x - One.Origin.x,
y - One.Origin.y), angle);
Two.Data[finalVec.x + One.Origin.x][finalVec.y + One.Origin.y] = true;
}
}
}
///Copy the second square back into the first
for (int y = 0; y < H; ++y) {
for (int x = 0; x < W; ++x)
One.Data[x][y] = Two.Data[x][y];
}
One.draw();
return 0;
}
Is this due to the accuracy of the newPos() function, or is it the rounding into int values that is causing this?
Additionally, is there a way to fix this or predict where the holes will be?
EDIT: SOLVED!
Going off of infgeoax's suggestion to work backwards, I created a function to calculate the original positions. I'll leave the augmented code here, in case anyone has a similar problem in the future (Thanks for all your help, everyone! [especially infgeoax, for the brainwave]):
#include <iostream>
#include <cmath>
using namespace std;
enum {W = 50, H = 50, S = 25};
struct Vector2i
{
int x;
int y;
Vector2i() {}
Vector2i(int _x, int _y) : x(_x), y(_y) {}
};
struct Square
{
bool Data[W][H];;
Vector2i Origin = Vector2i(W / 2, H / 2);
void clear() {
for (int y = 0; y < H; ++y) {
for (int x = 0; x < W; ++x)
Data[x][y] = false;
}
}
void setSquare() {
for (int y = H / 2 - S / 2; y < H / 2 + S / 2; ++y) {
for (int x = W / 2 - S / 2; x < W / 2 + S / 2; ++x)
Data[x][y] = true;
}
}
void draw() {
for (int y = 0; y < H; ++y) {
for (int x = 0; x < W; ++x) {
if (y == Origin.y && x == Origin.x) std::cout << '+'; //Marks the origin
else if (Data[x][y]) std::cout << 'X';
else std::cout << '.';
}
std::cout << '\n';
}
}
};
Vector2i oldPos(Vector2i new_, float theta) {
theta *= 3.14159265f / 180.f; //Converting from degrees to radians
return Vector2i(new_.x * cosf(theta) + new_.y * sinf(theta) + 0.5f,
new_.y * cosf(theta) - new_.x * sinf(theta) + 0.5f);
}
int main()
{
cout << "Enter an angle (in degrees): ";
float angle = 0;
cin >> angle;
Square One;
One.clear();
One.setSquare();
One.draw();
Square Two;
Two.clear();
for (int y = 0; y < H; ++y) {
for (int x = 0; x < W; ++x) {
Vector2i vec = oldPos(Vector2i(x - One.Origin.x, y - One.Origin.y), angle);
vec.x += One.Origin.x;
vec.y += One.Origin.y;
if (vec.x >= 0 && vec.x < W && vec.y >= 0 && vec.y < H)
Two.Data[x][y] = One.Data[vec.x][vec.y];
}
}
Two.draw();
return 0;
}
Well your problem has nothing to do with whether or not your are developing a console or GUI application. Images are stored and processed as matrices of pixels. When you rotate the image, the resulting position for a specific pixel is usually not integers.
The idea is to go the other way around.
You calculate the four corners of the rotated sqaure.
For each position(pixel) in the rotated square, you calculate its color by rotating it back to the original square.