C++ macro (min max) not working properly - c++

Why doesn't the following code work? It prints INT_MAX. But if I uncomment the two lines in the inner for loop, then it works fine (prints 2). I can't combine the two macros like that? Not sure if further detail is needed...pretty self explanatory.
Thanks.
#include <iostream>
#include <limits.h>
using namespace std;
#define min(a,b) a<b?a:b
#define max(a,b) a>b?a:b
int main(int argc, char **argv)
{
int N = 100;
int *drop = new int[N+1];
drop[0] = 0; drop[1] = 1; drop[2] = 1;
for(int i=3; i<=N; i++)
{
drop[i] = INT_MAX;
for(int start=1; start<=i; start++)
{
drop[i] = min(drop[i], max(start, drop[i-start]+1));
//int x = max(start, drop[i-start]+1);
//drop[i] = min(drop[i], x);
}
}
cout<<drop[3]<<endl;
return 0;
}

Put brackets around the terms in your macros:
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
As it is, this:
drop[i] = min(drop[i], max(start, drop[i-start]+1));
is expanding to this (without brackets):
drop[i] < start > drop[i-start]+1 ? start: drop[i-start]+1 ? drop[i] : start > drop[i-start]+1 ? start: drop[i-start]+1;
which may not evaluate in the order you intend. Using brackets enforces the correct order of operations.
As noted in the comments, you shouldn't use macros with expressions that have side effects if the macro arguments are evaluated more than once.

C++ already has std::min and std::max defined in <algorithm>. You can change your code to a pure C++ version
#include <iostream>
#include <algorithm>
#include <limits>
using namespace std;
int main(int argc, char ** argv) {
int N = 100;
int * drop = new int[N + 1];
drop[0] = 0;
drop[1] = drop[2] = 1;
for (int i = 3; i <= N; ++i) {
drop[i] = numeric_limits<int>::max(); // <limits>
for(int start = 1; start <= i; ++start)
drop[i] = min(drop[i], max(start, drop[i - start] + 1)); // <algorithm>
}
cout << drop[3] << endl;
return 0;
}

Rather than an answer, it's a plead to all developers out there: please don't use macros like that. C++ offers template functions for these purposes. Remember that macros just substitute parameters rather than pre-evaluating them. Even if you add parentheses as samgak explained, this only fixes a half of the problem. Consider code like this:
int x = 5;
int y = max(++x, 0);
The caller would expect x=6 and y=6 after that; however the macro will get expended into
int y = (++x > 0)? ++x : 0;
causing x=7 and y=7.

Related

C++ Not getting expected result when executing a Macro

#include <stdio.h>
#define swapOut(a,b) a+b-a, a+b-b
int main()
{
int a = 5;
int b = 6;
printf("%d,%d", swapOut(a+b,b-a));
return 0;
}
When executing this program, I am expecting the output to be "1,11", but the actual output is "13,1". Can someone explain what is happening here ?
To understand what's happening, you have to realise that macros are not like functions; they perform very simple text substitution. Thus, when you define
#define swapOut(a,b) a+b-a, a+b-b
and then use it as swapOut(a+b,b-a), it is expanded as a+b+b-a-a+b, a+b+b-a-b-a. With the values a=5 and b=6 this results in 13,1.
So here's a valuable lesson: always surround the arguments in macros with parentheses. The corrected version of your program is
#include <stdio.h>
#define swapOut(a,b) ((a)+(b)-(a)), ((a)+(b)-(b))
int main()
{
int a = 5;
int b = 6;
printf("%d,%d", swapOut(a+b,b-a));
return 0;
}
This indeed outputs 1,11 as you expected.
To achieve this, you have to localize the value first.
#include <stdio.h>
#define swapOut(a,b) a+b-a, a+b-b
int main()
{
int a = 5;
int b = 6;
int c = a + b;
int d = b - a;
printf("%d,%d", swapOut(c,d));
return 0;
}

How to find the minimun of an array?

I was trying to solve this question
but codechef.com says the answer is wrong.
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int t, n, diff, mindiff;
cin >> t;
cin >> n;
int val[n];
while(t--)
{
mindiff = 1000000000;
for(int i = 0; i<n; i++)
{
cin >> val[i];
}
int a = 0;
for(a = 0; a<n ; a++)
{
for(int b=a+1; b<n ; b++)
{
diff = abs(val[a] - val[b]);
if(diff <= mindiff)
{
mindiff = diff;
}
}
}
cout << mindiff << endl;
}
return 0;
}
The results are as expected (for at least the tests I did) buts the website says its wrong.
There are a few things in your code that you should change:
Use std::vector<int> and not variable-length arrays (VLA's):
Reasons:
Variable length arrays are not standard C++. A std::vector is standard C++.
Variable length arrays may exhaust stack memory if the number of entries is large. A std::vector gets its memory from the heap, not the stack.
Variable length arrays suffer from the same problem as regular arrays -- going beyond the bounds of the array leads to undefined
behavior. A std::array has an at() function that can check boundary access when desired.
Use the maximum int to get the maximum integer value.
Instead of
mindif = 1000000000;
it should be:
#include <climits>
//...
int mindiff = std::numeric_limits<int>::max();
As to the solution you chose, the comments in the main section about the nested loop should be addressed.
Instead of a nested for loop, you should sort the data first. Thus finding the minimum value between two values is much easier and with less time complexity.
The program can look something like this (using the data provided at the link):
#include <iostream>
#include <vector>
#include <climits>
#include <algorithm>
int main()
{
int n = 5;
std::vector<int> val = {4, 9, 1, 32, 13};
int mindiff = std::numeric_limits<int>::max();
std::sort(val.begin(), val.end());
for(int a = 0; a < n-1 ; a++)
mindiff = std::min(val[a+1] - val[a], mindiff);
std::cout << mindiff;
}
Output:
3
To do this you can use a simple for():
// you already have an array called "arr" which contains some numbers.
int biggestNumber = 0;
for (int i = 0; i < arr.size(); i++) {
if (arr[i] > biggestNumber) {
biggestNumber = arr[i];
}
}
arr.size will get the array's length so that you can check every value from the position 0 to the last one which is arr.size() - 1 (because arrays are 0 based in c++).
Hope this helps.

c++ - Fill a symmetric matrix using an array stored on the heap

I am trying to build a code where I have to declare a large array in the heap.
At the same time I will use the boost library to perform some matrix calculations (as can be seen in Fill a symmetric matrix using an array
).
My limitations here are two : I will deal with large arrays and matrices so I have to declare everything on the heap and I have to work with arrays and not with vectors.
However I am facing a rather trivial for many people problem... When filling the matrix, the last element doesn't get filled in correctly. So although I expect to get
[3,3]((0,1,3),(1,2,4),(3,4,5))
the output of the code is
[3,3]((0,1,3),(1,2,4),(3,4,2.6681e-315))
I am compiling this code in ROOT6. I don't think it's related to that, I am just mentioning it for completion.
A small sample of the code follows
#include <iterator>
#include <iostream>
#include <fstream>
#include </usr/include/boost/numeric/ublas/matrix.hpp>
#include </usr/include/boost/numeric/ublas/matrix_sparse.hpp>
#include </usr/include/boost/numeric/ublas/symmetric.hpp>
#include </usr/include/boost/numeric/ublas/io.hpp>
using namespace std;
int test_boost () {
using namespace boost::numeric::ublas;
symmetric_matrix<double, upper> m_sym1 (3, 3);
float* filler = new float[6];
for (int i = 0; i<6; ++i) filler[i] = i;
float const* in1 = filler;
for (size_t i = 0; i < m_sym1.size1(); ++ i)
for (size_t j = 0; j <= i && in1 != &filler[5]; ++ j)
m_sym1 (i, j) = *in1++;
delete[] filler;
std::cout << m_sym1 << std::endl;
return 0;
}
Any idea on how to solve that?
Arrays and pointers are not objects of class type, they don't have members. You already have a float *, it is filler.
float const* in1 = filler; // adding const is always allowed
I've manged to finally solve it by changing &filler[5] to &filler[6].
So a version that works is seen below
#include <iterator>
#include <iostream>
#include <fstream>
#include </usr/include/boost/numeric/ublas/matrix.hpp>
#include </usr/include/boost/numeric/ublas/matrix_sparse.hpp>
#include </usr/include/boost/numeric/ublas/symmetric.hpp>
#include </usr/include/boost/numeric/ublas/io.hpp>
using namespace std;
int test_boost () {
using namespace boost::numeric::ublas;
symmetric_matrix<double, upper> m_sym1 (3, 3);
float* filler = new float[6];
for (int i = 0; i<6; ++i) filler[i] = i;
float const* in1 = filler;
for (size_t i = 0; i < m_sym1.size1(); ++ i)
for (size_t j = 0; j <= i && in1 != &filler[6]; ++ j)
m_sym1 (i, j) = *in1++;
delete[] filler;
std::cout << m_sym1 << std::endl;
return 0;
}
Running this code yields the following output
[3,3]((0,1,3),(1,2,4),(3,4,5))

Can I Use vector's Fill Constructor to Create a Multi-Dimensional Array? [duplicate]

I'm trying to do something like:
#include <iostream>
#include <vector>
#include <ctime>
class Clickomania
{
public:
Clickomania();
std::vector<std::vector<int> > board;
};
Clickomania::Clickomania()
: board(12, std::vector<int>(8,0)) <<<<<<<
{
srand((unsigned)time(0));
for(int i = 0; i < 12; i++)
{
for(int j = 0; j < 8; j++)
{
int color = (rand() % 6) + 1;
board[i][j] = color;
}
}
}
However, apparently I can't initialize the "board" vector of vectors this way.
How can I create a public member of a 2d vector type and initialize it properly?
you should use the constructor that allows you to specify size and initial value for both vectors which may make it a bit easier altogether.
something like:
vector<vector<int>> v2DVector(3, vector<int>(2,0));
should work.
Use a matrix instead:
(Basic example from boost documentation)
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
int main () {
using namespace boost::numeric::ublas;
matrix<double> m (3, 3);
for (unsigned i = 0; i < m.size1 (); ++ i)
for (unsigned j = 0; j < m.size2 (); ++ j)
m (i, j) = 3 * i + j;
std::cout << m << std::endl;
}
Compiling your code with g++, the error I get is that neither srand() nor rand() were declared. I had to add #include <cstdlib> for the code to compile. But once I did that, it worked just fine. So, I'd say that other than adding that include statement, your code is fine. You're initializing the vector correctly.
Perhaps the code you have doesn't quite match what you posted? I would assume that if your actual code didn't include cstdlib, that you would have quickly understood that that was the problem rather than something with vector. So, if your code doesn't quite match what you posted, maybe that's the problem. If not, what compiler are you using?

Library incompatibility? - C++

I'm trying to solve 56th problem of Project Euler and I have some troubles while using the Big Integer Library. Here is the code :
#include <iostream>
#include "BigInteger.hh"
#include <cmath>
using namespace std;
int digitSum(BigInteger x){
int num[(int)floor(log10(x))+2];
int n = 0;
BigInteger sum = 0;
while (x != 0){
sum += x - floor(x/10) * 10;
x = floor(x/10);
n++;
}
return sum.toInt();
}
int main(int argc, const char * argv[])
{
int max = 0;
for (int i = 1; i <= 100; i++){
for (int j = 1; j <= 100; j++){
cout << "i = %i, j = %i ",i,j;
if (digitSum(pow(i,j)) < max)
max = digitSum(pow(i,j));
}
}
cout << digitSum(pow(2,63));
return 0;
}
The problem is that when I try building, the compiler gives error on the lines using the log10, floor, and pow functions saying that they are used but not defined. When I comment the line #include "BigInteger.hh", everything goes fine but this time, of course, I can't use the Big Integer library.
Why is there such a problem? How to solve it?
Is it a compiler or a linker problem? If latter, try adding -lm to the command line to link the math library. Assuming GNU gcc here.