Greedy algorithm exercise not working properly - c++

I'm in high school and having a test soon, one of the topics being the Greedy algorithm. I'm having an unknown issue with this exercise: "It is given an array of N integers. Using the Greedy algorithm, determine the largest number that can be written as a multiplication of two of the array elements" (Sorry if it's a bit unclear, I'm not a native English speaker).
Now, what I had in mind to solve this exercise is this: Find the largest two numbers and the lowest two numbers (in case they are both negative) and display either the multiplication of the two largest or of the two lowest, depending on which number is larger.
This is what I wrote:
#include <iostream>
using namespace std;
int a[100001],n;
int main()
{
int max1=-1000001,max2=-1000001,min1=1000001,min2=1000001,x;
cin>>n;
for (int i=1; i<=n; i++)
{
cin>>a[i];
if (a[i]>=max2)
{
if (a[i]>=max1)
{
x=max1;
max1=a[i];
max2=x;
}
else max2=a[i];
}
if (a[i]<=min2)
{
if (a[i]<=min1)
{
x=min1;
min1=a[i];
min2=x;
}
else min2=a[i];
}
}
if (n==1)
cout<<n;
else if (max1*max2>=min1*min2)
cout<<max1*max2;
else cout<<min1*min2;
return 0;
}
Yes, I know the way I wrote it is untidy/ugly. The code, however, should function properly and I tested it with both the example provided by the exercise and lots of different situations. They all gave the right result. The problem is that the programming exercises website gives my code a 80/100 score, not because of the time but because of the wrong answers.
I've already spent more than 2 hours looking at this code and I just can't figure out what's wrong with it. Can anyone point out the flaw? Thanks <3

The problem most likely comes from the fact that multiplying 2 int's will give you an int. An int usually has a range of -2,147,483,648 to 2,147,483,647.
If you then multiply 2,147,483,647 * 2 for example you get -2. Similarly taking 2,147,483,647 + 1 will give you -2147483648. When the value reaches it's max it deals with that by going to the lowest possible value.
To partially solve the problem you just need to cast 1 of the variables you multiply to a 64-bit integer. For modern C++ that would be int64_t.
if (n==1)
cout<<n;
else if (static_cast<int64_t>(max1)*max2>=static_cast<int64_t>(min1)*min2)
cout<<static_cast<int64_t>(max1)*max2;
else cout<<static_cast<int64_t>(min1)*min2;
But you will still be able to get too big number if both the values are big enough. So you need the full range of a uint64_t, the unsigned version.
So we need to cast to a uint64_t instead, but then you run into another issue with the numbers below 0. So first you should convert you min1 and min2 to the equivalent positive numbers, then cast to uint64_t.
uint64_t positive_min1, positive_min2;
if (min1 < 0 && min2 < 0) {
positive_min1 = min1*-1;
positive_min2 = min2*-1;
}
else {
positive_min1 = 0;
positive_min2 = 0;
}
Now you can go ahead and do
if (n==1)
cout<<n;
else if (static_cast<uint64_t>(max1)*max2>=positive_min1*positive_min2)
cout<<static_cast<int64_t>(max1)*max2;
else cout<<positive_min1*positive_min2;
No need to cast positive_min1 & 2 since it was already converted to uint64_t.
Since you are casting max1 to unsigned, you should probably check that it's not below 0 first.
If signed and unsigned is not familiar concepts you can read about that and the different data types here.

Related

sieve or eratosthenes calculator -- running into memory issues and crashing with numbers >=1,000,000

I'm not exactly sure why this is. I tried changing the variables to long long, and I even tried doing a few other things -- but its either about the inefficiency of my code (it literally does the whole process of finding all primes up to the number, then checking against the number to see if its divisible by that prime -- very inefficient, but its my first attempt at this and I feel pretty accomplished having it work at all....)
Or the fact that it overflows the stack. Im not sure where it is exactly, but all I know is that it MUST be related to memory and the way its dealing with the number.
If I had to guess, Id say its a memory issue happening when it is dealing with the prime number generation up to that number -- thats where it dies even if I remove the check against the input number.
I'll post my code -- just be aware, I didnt change long long back to int in a few places, and I also have a SquareRoot Variable that is not used, because it was supposed to try and help memory efficiency but was not effective the way I tried to do it. I Just never deleted it. I will clean up the code when and if I can successfully finish it.
As far as I am aware though, it DOES work pretty reliably for 999,999 and down, I actually checked it up against other calculators of the same type and it seemingly does generate the proper answers.
If anyone can help or explain what I screwed up here, your helping a guy trying to learn on his own without any school or anything. so its appreciated.
#include <iostream>
#include <cmath>
void sieve(int ubound, int primes[]);
int main()
{
long long n;
int i;
std::cout << "Input Number: ";
std::cin >> n;
if (n < 2) {
return 1;
}
long long upperbound = n;
int A[upperbound];
int SquareRoot = sqrt(upperbound);
sieve(upperbound, A);
for (i = 0; i < upperbound; i++) {
if (A[i] == 1 && upperbound % i == 0) {
std::cout << " " << i << " ";
}
}
return 0;
}
void sieve(int ubound, int primes[])
{
long long i, j, m;
for (i = 0; i < ubound; i++) {
primes[i] = 1;
}
primes[0] = 0, primes[1] = 0;
for (i = 2; i < ubound; i++) {
for(j = i * i; j < ubound; j += i) {
primes[j] = 0;
}
}
}
If you used legal C++ constructs instead of non-standard variable length arrays, your code will run (whether it produces the correct answers is another question).
The issue is more than likely that you're exceeding the limits of the stack when you declare arrays with a million or more elements.
Therefore instead of this:
long long upperbound = n;
A[upperbound];
Use std::vector:
#include <vector>
//...
long long upperbound = n;
std::vector<int> A(upperbound);
and then:
sieve(upperbound, A.data());
The std::vector does not use the stack space to allocate its elements (unless you have written an allocator for it that uses the stack).
As a matter of fact, you don't even need to pass upperbound to sieve, as a std::vector knows its own size by calling the size() member function. But I leave that as an exercise.
Live example using 2,000,000
First of all, read and apply PaulMcKenzie's advice. That's the most important thing. I'm only addressing some teeny bits of your question that remained open.
It seems that you are trying to factor the number that you misleadingly called upperbound. The mysterious role of the square root of this number is related to this fact: if the number is composite at all - and hence can be computed as the product of some prime factors - then the smallest of these prime factors cannot be greater than the square root of the number. In fact, only one factor can possibly be greater, all others cannot exceed the square root.
However, in its present form your code cannot draw advantage from this fact. The trial division loop as it stands now has to run up to number_to_be_factored / 2 in order not to miss any factors because its body looks like this:
if (sieve[i] == 1 && number_to_be_factored % i == 0) {
std::cout << " " << i << " ";
}
You can factor much more efficiently if you refactor your code a bit: when you have found the smallest prime factor p of your number then the remaining factors to be found must be precisely those of rest = number_to_be_factored / p (or n = n / p, if you will), and none of the remaining factors can be smaller than p. However, don't forget that p might occur more than once as a factor.
During any round of the proceedings you only need to consider the prime factors between p and the square root of the current number; if none of those primes divides the current number then it must be prime. To test whether p exceeds the square root of some number n you can use if (p * p > n), which is computationally more efficient that actually computing the square root.
Hence the square root occurs in two different roles:
the square root of the number to be factored limits the amount of sieving that needs to be done
during the trial division loop, the square root of the current number gives an upper bound for the highest prime factor that you need to consider
That's two faces of the same coin but two different usages in the actual code.
Note: once you got your code working by applying PaulMcKenzie's advice, you might also to consider posting over on Code Review.

Program taking too long for large input

I am using an equation in which we have to find the maximum value that x can take given the value of b. Both x and b can take only nonnegative integer values. The equation is:
x^4+x^3+x^2+x+1≤b
I have written the following code(apparently dumb) to solve it:
#include<iostream>
#include<climits>
using namespace std;
int main()
{
unsigned long long b,x=0;
cout<<"hey bro, value of b:";
cin>>b;
while(x++<b)
if(x*x*x*x+x*x*x+x*x+x+1>b)
break;
if(b==0)
cout<<"Sorry,no value of x satisfies the inequality"<<endl;
else
cout<<"max value of x:"<<x-1<<endl;
return 0;
}
The above code works fine upto b=LONG_MAX but after for b=LONG_LONG_MAX or b=ULLONG_MAX, it starts taking forever. How can I solve this problem so that it works fine for at most b=ULLONG_MAX?
If for x = m, the inequality holds, then it also holds for all integers < m. If it doesn't hold for m, then it doesn't hold for any integer > m. What algorithm does this suggest?
If you want to spoil yourself, click here for the algorithm.
This is not just an optimization issue. (For optimization, see IVlad's answer). It is also a correctness issue. With very large values, the expression causes integer overflow: to put it simply, it wraps around from ULLONG_MAX back to zero, and your loop carries on having not detected this. You need to build overflow detection in your code.
A really simple observation solves your problem in O(1) time.
Find k = sqrt(sqrt(b))
If k satisfies your inequality, k is your answer. If it does not, k-1 is your answer.
Old answer (real problem here is not big number of iterations, but integer overflow; please read from 'Update' part; I keep this part here for history of false assumptions):
These values are very big. When your program checks each value from 0 to LONG_LONG_MAX, it shold make about 9*10^12 operations, isn't it? For ULLONG_MAX we have about 18*10^12 operations. Try to modify this program to see actual speed of processing:
while (x++ < b)
{
if (x % 1000000 == 0)
cout << " current x: " << x << endl;
if (x*x*x*x+x*x*x+x*x+x+1>b)
break;
}
So, you need to optimize this algorithm (i.e. reduce number of iterations): since your function is monotonic, you can use Binary search algorithm (see Bisection method too for clarification).
Also there is a possible problem with integer overflow: function x*x*x*x for big values x will be calculated wrong. Just imagine thay your type is unsigned char (1 byte). For example, when your program calculates 250*250*250*250 you expect 3906250000, but in fact you have 3906250000 % 256 (i.e. 16). So, if x is too big, it is possible, that your function will return value < b (and it will be strange; theoretically it can brake your optimized algorithm). Good news is that you will not see this problem, if do every check correctly. But for more complex functions you would also need to support long math (for example, use GMP or another implementation).
Update: How to avoid overflow risks?
We need to find maximal allowed value of x (let's call it xmax). Value x is allowed if x*x*x*x+x*x*x+x*x+x+1 < ULLONG_MAX. So, answer on initial question (about x*x*x*x+x*x*x+x*x+x+1 < b) is not bigger than xmax. Let's find xmax (just solve equation x*x*x*x+x*x*x+x*x+x+1=ULLONG_MAX in any system, for example WolframAlpha: anwer is about 65535.75..., so xmax==65535. So, if we check x from 0 to xmax we will not have overflow problems. Also it is our initial values for binary search algorithm.
Also it means, that we do not need to use binary search algorithm here, because it is enought to check only 65535 values. If x==65535 is not answer, we have to stop and return answer 65536.
If we need cross-platform solution without hardcoding of xmax, we can use any bigint implementation (GMP or any simpler solution) or implement more accurate multiplication and other operations. Example: if we need to multyply x and y, we can calculate z=ULLONG_MAX/x and compare this value and y. If z<y, we can't multiply x and y without overflow.
You could try finding an upper limit and working down from there.
// Find the position of the most significant bit.
int topBitPosition = 0;
while(b >> topBitPosition)
topBitPosition++;
// Find a rough estimate of b ^ 1/4
unsigned long long x = b >> (topBitPosition - topBitPosition/4);
// Work down from there
while(x*x*x*x+x*x*x+x*x+x+1 > b)
x--;
cout<<"max value of x:"<<x-1<<endl;
Don't let x exceed 65535. If 65535 satisfies the inequality, 65536 will not.
Quick answer:
First af all you are starting from x=0 and then increasing it which is not the best solution since you are looking for the maximum value and not the first one.
So for that I would go from an upperbound that can be
x=abs((b)^(1/4))
than decrease from that value, and as soon you find an element <=b you are done.
You can even think in this way:
for y=b to 1
solve(x^4+x^3+x^2+x+1=y)
if has an integer solution then return solution
See this
This is a super quick answer I hope I didn't write too many stupid things, and sorry I don't know yet how to write math here.
Here's a slightly more optimized version:
#include<iostream>
int main()
{
std::cout << "Sorry, no value of x satisfies the inequality" << std::endl;
return 0;
}
Why? Because x^4+x^3+x^2+x+1 is unbounded as x approaches positive infinity. There is no b for which your inequality holds. Computer Science is a subset of math.

Wrong result for code doing dynamic programming in C++

I am solving a dp problem .The problem is that I have N dices; each of them has K faces numbered from 1 to K. Now I have arranged the N dices in a line. I can rotate/flip any dice if I want. How many ways I can set the top faces such that the summation of all the top faces equals S?
Now I am given N, K, S; I have to calculate the total number of ways.It is worthy of mention I have to print the result modulo 100000007.I have tried to solve this problem and write a code for this one but my code doesn't work for this case:800 800 10000 why? I can't understand .Can anyone explain the cause for which my code doesn't work. My code is here:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<memory.h>
#define M 100000007
#define ull unsigned long long
using namespace std;
ull n,K,s,dp[1001][1001];
ull fnc(int num,int sum,int k)
{
ull temp;
if(num==0){
if(sum==0) return 1;
else return 0;
}
if(dp[num][k]!=-1)
return dp[num][k];
for(int i=1;i<=K;i++)
{
temp=temp%M+fnc(num-1,sum-i,i)%M;
}
return dp[num][k]=temp%M;
}
int main()
{
int T;
cin>>T;
for(int t=1;t<=T;t++)
{
cin>>n>>K>>s;
memset(dp,-1,sizeof(dp));
printf("Case %d: %lld\n",t,fnc(n,s,0));
}
return 0;
}
You used the wrong subscripts for dp.
Consider how many ways you can get 800 dice, each with numbers from 1 to 800,
to have the sum 10000 if you make the number 1 uppermost on the first die
and you make 4 uppermost on the second die.
Now consider how many ways to have the sum 10000 if you make 2 uppermost on the first die
and 3 uppermost on the second die.
Those two quantities are the same: each is the number of ways to get 798 dice (with numbers 1 to 800) to have the sum 99995. That is the kind of quantity you want to memoize.
But you have not even allocated enough space in dp to store this kind of partial answer.
I also have to wonder why you are using unsigned long long rather than just unsigned long, since your answer is to be given modulo 100000007. You should never have to
work with numbers that are even near the maximum value of a signed long.
According to http://linux.die.net/man/3/memset :
The memset() function fills the first n bytes of the memory area pointed to by s with the constant byte c.
Note it doesn't say "the constant unsigned long long c".
You have the value k and K defined in the same scope, which is infuriating.
You hard coded 1001 and -1 instead of giving them proper soft coded variable names.
Most of your variable names are 1 character long.
You have persistent behavior in a return statement.
You have absolutely nothing checking if the values of k, K, and num are within the proper range of dp, which is partially a consequence of hard coding 1001.
Spacebar is your friend, writingcodelikethisthatwehavetoreadisannoying.

Polynomial hash code results in negative numbers?

For large j in certain cases functions the hash function below returns negative values.
int hashing::hash(string a)
{
int i = 0;
int hvalue = 0;
int h =0 ;
while(a[i]!=NULL)
{
hvalue = hvalue + (int(a[i]))*pow(31,i);
i++;
}
h = hvalue%j;
return h;
}
How is that possible? How can I correct it?
In the above code, j is a prime number calculated using the size of the file. The negative values arise in certain specific cases where the string has the form " the s".
What am I doing wrong? How can I fix it?
Remember that int has a finite range and is (usually) a signed value. That means that if you exceed the maximum possible value for an int, it will wrap around and might become negative.
There are a couple of ways you could fix that. First, you could switch to using unsigned ints to hold the hash code, which are never negative and will behave nicely when wrapping around. Alternatively, if you still want to use ints, you can mask off the sign bit (the bit at the front of the number that makes the value negative) by doing this:
return (hvalue & INT_MAX) % j;
(Here, INT_MAX is defined in <climits>). This will ensure your value is positive, though you lose a bit from your hash code, which might for large data sets lead to some more clustering. The reason for doing the & before the mod is that you want to ensure the value is positive before taking the mod, since otherwise you'll overflow the number of buckets.
EDIT: You also have a serious error in your logic. This loops is incorrect:
while(a[i]!=NULL) {
...
}
C++-style strings aren't null-terminated, so this isn't guaranteed to stop once you read past the end of the string. Try changing this to read
for (int i = 0; i < a.length(); i++) {
/* ... process a[i] ... */
}
Hope this helps!

C++ program to calculate quotients of large factorials

How can I write a c++ program to calculate large factorials.
Example, if I want to calculate (100!) / (99!), we know the answer is 100, but if i calculate the factorials of the numerator and denominator individually, both the numbers are gigantically large.
expanding on Dirk's answer (which imo is the correct one):
#include "math.h"
#include "stdio.h"
int main(){
printf("%lf\n", (100.0/99.0) * exp(lgamma(100)-lgamma(99)) );
}
try it, it really does what you want even though it looks a little crazy if you are not familiar with it. Using a bigint library is going to be wildly inefficient. Taking exps of logs of gammas is super fast. This runs instantly.
The reason you need to multiply by 100/99 is that gamma is equivalent to n-1! not n!. So yeah, you could just do exp(lgamma(101)-lgamma(100)) instead. Also, gamma is defined for more than just integers.
You can use the Gamma function instead, see the Wikipedia page which also pointers to code.
Of course this particular expression should be optimized, but as for the title question, I like GMP because it offers a decent C++ interface, and is readily available.
#include <iostream>
#include <gmpxx.h>
mpz_class fact(unsigned int n)
{
mpz_class result(n);
while(n --> 1) result *= n;
return result;
}
int main()
{
mpz_class result = fact(100) / fact(99);
std::cout << result.get_str(10) << std::endl;
}
compiles on Linux with g++ -Wall -Wextra -o test test.cc -lgmpxx -lgmp
By the sounds of your comments, you also want to calculate expressions like 100!/(96!*4!).
Having "cancelled out the 96", leaving yourself with (97 * ... * 100)/4!, you can then keep the arithmetic within smaller bounds by taking as few numbers "from the top" as possible as you go. So, in this case:
i = 96
j = 4
result = i
while (i <= 100) or (j > 1)
if (j > 1) and (result % j == 0)
result /= j
--j
else
result *= i
++i
You can of course be cleverer than that in the same vein.
This just delays the inevitable, though: eventually you reach the limits of your fixed-size type. Factorials explode so quickly that for heavy-duty use you're going to need multiple-precision.
Here's an example of how to do so:
http://www.daniweb.com/code/snippet216490.html
The approach they take is to store the big #s as a character array of digits.
Also see this SO question: Calculate the factorial of an arbitrarily large number, showing all the digits
You can use a big integer library like gmp which can handle arbitrarily large integers.
The only optimization that can be made here (considering that in m!/n! m is larger than n) means crossing out everything you can before using multiplication.
If m is less than n we would have to swap the elements first, then calculate the factorial and then make something like 1 / result. Note that the result in this case would be double and you should handle it as double.
Here is the code.
if (m == n) return 1;
// If 'm' is less than 'n' we would have
// to calculate the denominator first and then
// make one division operation
bool need_swap = (m < n);
if (need_swap) std::swap(m, n);
// #note You could also use some BIG integer implementation,
// if your factorial would still be big after crossing some values
// Store the result here
int result = 1;
for (int i = m; i > n; --i) {
result *= i;
}
// Here comes the division if needed
// After that, we swap the elements back
if (need_swap) {
// Note the double here
// If m is always > n then these lines are not needed
double fractional_result = (double)1 / result;
std::swap(m, n);
}
Also to mention (if you need some big int implementation and want to do it yourself) - the best approach that is not so hard to implement is to treat your int as a sequence of blocks and the best is to split your int to series, that contain 4 digits each.
Example: 1234 | 4567 | 2323 | 2345 | .... Then you'll have to implement every basic operation that you need (sum, mult, maybe pow, division is actually a tough one).
To solve x!/y! for x > y:
int product = 1;
for(int i=0; i < x - y; i ++)
{
product *= x-i;
}
If y > x switch the variables and take the reciprocal of your solution.
I asked a similar question, and got some pointers to some libraries:
How can I calculate a factorial in C# using a library call?
It depends on whether or not you need all the digits, or just something close. If you just want something close, Stirling's Approximation is a good place to start.