Wrong Solution if Memoization is added to Recursion - c++

I have created a DP program but the problem is that I get correct answers when I don't use memoization. As soon as I introduce memoization, I start getting the wrong answers for some problems
Here is the code in C++ 14 with memoization turned off (By commenting)
#include <iostream>
#include <math.h>
#include<algorithm>
using namespace std;
int max_Number_of_turns;
int dp[9999][1000];
int changeTheDigit(int n, int d) {
int rem = n % (int) (pow(10, 4 - d));
n /= (pow(10, 4 - d));
int x = n % 10;
n /= 10;
if (x == 9) x = 0;
else x = x + 1;
n = n * (10) + x;
n = n * (pow(10, 4 - d)) + rem;
return n;
}
int minMax(int n, int t) {
int ans =0;
//if(dp[n][t]>=0) { return dp[n][t];}
if (t > max_Number_of_turns) return n;
int N;
for (int i = 0; i < 4; i++) {
N = changeTheDigit(n, i + 1);
if (t % 2 == 0) {
//Manish chance
if(ans==0) ans=minMax(N, t+1);
else ans = min(ans, minMax(N, t + 1));
} else {
//Nitish Chance
ans = max(ans, minMax(N, t + 1));
}
}
//cout << ans << endl;
dp[n][t]=ans;
return ans;
}
using namespace std;
int main() {
int T, N, M;
cin >> T;
while (T--) {
cin >> N >> M;
max_Number_of_turns=M;
for(int i=0;i<9999;i++)
for(int j=0;j<1000;j++)
dp[i][j]=-1;
if(minMax(N,1)>N){
cout << "Nitish" << endl;
}
else{
cout << "Manish" << endl;
}
}
return 0;
}
Turn the memoization comment on (i.e. remove the comments from this line)
if(dp[n][t]>=0) { return dp[n][t];}
and my code will give wrong answers to some problems
For example, let us consider the input
1
4569 12
Original Correct Solution is Manish
But If I turn on memoization, My solution is Nitish
Can you suggest me that what am I doing wrong here
Also, a fun fact is that, if the change the DP code from
if(dp[n][t]>=0) { return dp[n][t];}
to
if(dp[n][t]>0) { return dp[n][t];}
Then everything is fine

Your problem is that the values for n and/or t are not checked and so could cause out-of-bounds issues with the array. You can see that if you insert the following at the start of your minMax function:
if (n < 0 || n >= 9999) cout << "n invalid at " << n << '\n';
if (t < 0 || t >= 1000) cout << "t invalid at " << t << '\n';
Running that with your sample input gives warnings before outputting the result:
n invalid at 9999
n invalid at 9999
n invalid at 9999
To fix this, you can just ensure you only use memoisation when you have enough storage for it, first when checking the value:
if (n >= 0 && n < 9999 && t >= 0 && t < 1000 && dp[n][t] >= 0)
return dp[n][t];
and, second, when storing the value:
if (n >= 0 && n < 9999 && t >= 0 && t < 1000)
dp[n][t] = ans;

Related

Can anyone explain what is the error I am getting in the output and how to remove it?

My code:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int BinaryToDecimal(int n)
{
int ans = 0;
int x = 1;
while (n > 0)
{
int y = n % 10;
ans = ans + x * y;
x = x * 2;
n = n / 10;
}
return ans;
}
int DecimalToBinary(int num)
{
vector<int> vect;
while (num > 0)
{
vect.push_back(num % 2);
num = num / 2;
}
int s = vect.size();
int i = s - 1;
for (i = s - 1; i >= 0; i--)
{
cout << vect.at(i);
}
return vect.at(i);
}
int main()
{
int a, b;
cout << "Enter first number: " << endl;
cin >> a;
cout << "Enter second number: " << endl;
cin >> b;
int a_deci = BinaryToDecimal(a);
int b_deci = BinaryToDecimal(b);
int sum = a_deci + b_deci;
DecimalToBinary(sum);
cout << endl;
return 0;
}
Output:
Enter first number:
10101
Enter second number:
11010
101111terminate called after throwing an instance of 'std::out_of_range'what(): vector::_M_range_check: __n (which is 18446744073709551615) >= this->size() (which is 6)
What does this error message mean and how do I fix it?
After this for loop
for (i = s - 1; i >= 0; i--)
{
cout << vect.at(i);
}
the variable i is equal to -1.
So the next call of the member function at with the value equal to -1 (that yields a very big number of the unsigned type std::vector<int>::size_type)
return vect.at(i);
throws the exception.
It seems you need to return from the function the whole vector elements of which will represent a number in the binary form.
Instead of the container std::vector<int> it will be better to use std::bitset.

Are there any exceptions that I may have missed in this problem?

Recently I've been working on this problem on SPOJ:
Given a set of N integers A = {1, 2, 3, …, N} and an integer S, your task is find a way to insert an operator '+' or '-' to every neighbor pair of A, that the result of the expression after insert equal to S.
WARNING: You can't put any operators in front of 1.
Input:
A single line, including N and S (1 ≤ N ≤ 500, |S| ≤ 125250)
Output:
If there are way(s) to insert, output any of them, otherwise output “Impossible” (without quotes).
Example:
Input:
9 5
Output:
1-2+3-4+5-6+7-8+9
Input:
5 6
Output:
Impossible
I've already been messing up with these code, but SPOJ always yields that I've done this problem in the wrong way. I think there might be exceptions that I haven't found out.
int main()
{
int n;
cin >> n;
int a[501] = { };
int sum = 0;
for (int i = 1; i <= n; i++)
{
a[i] = 1;
sum += i;
}
int s;
cin >> s;
int aim = sum - s;
if ((aim % 2 != 0) || (s < -sum + 2) || (s > sum) || (s == -sum + 4) || (s == sum - 1))
{
cout << "Impossible" << endl;
return 0;
}
int c = n;
while (aim != 0)
{
if (aim >= c)
{
if (aim - 2 * c != 2)
{
aim -= (2 * c);
a[c] = -1;
c--;
}
else
{
a[c - 1] = -1;
a[2] = -1;
aim -= (2 * c + 2);
}
}
else
{
a[aim / 2] = -1;
aim = 0;
}
}
for (int i = 1; i <= n; i++)
if (a[i] == 1)
if (i == 1)
cout << i;
else
cout << "+" << i;
else
cout << "-" << i;
return 0;
}
You are subtracting 2 * c from aim after checking if aim >= c.
Changing the check to aim >= 2 * c will improve your program.

C++ : Why do I have to add a boolean expression?

The code is:
int main() {
int n, largest = 1;
cout << "enter :" << endl;
cin >> n;
int i = n - 1;
while(i > 0) {
if (n % i == 0){
largest = i;
}
i--;
}
cout << largest << endl;
system("pause");
return 0;
}
Why do these error occur? This code keeps making errors and my professor said that I should add a boolean expression. But I do not know why and where I have to add it?
(Inspired by Alexandrescu's CppCon 2019 talk)
Recall, that the control check on the loop is not necessary - we know that X % 1 is 0 for any X. Also, in-line with Alexandrescu's commitment to endless loops, we could rewrite the loop as following (it will have an added bonus of making it correct, but also will improve it's performance):
if (n <= 1) {
return;
}
largest = n - 1;
for (;; --largest) {
if (n % largest == 0)
break;
}
// Here largest is usable
Rewrite this loop
while( i > 0){
if ( n % i == 0){
largest = i;
}
i --;
}
for example like
while( i > 0 && n % i != 0 ) i--;
if ( i ) largest = i;
Also instead of the type int you should use the type unsigned int. Otherwise the user can enter a negative number. In this case the loop does not make sense.
Using your approach the program can look for example the following way
#include <iostream>
int main()
{
unsigned int n = 0, largest = 1;
std::cout << "enter a non-negative number: ";
std::cin >> n;
if ( n != 0 )
{
unsigned int i = n - 1;
while ( i > 0 && n % i != 0 ) i--;
if ( i ) largest = i;
}
std::cout << "The largest own divisor is " << largest << std::endl;
return 0;
}

Access violation reading location 0x50F9BF08

I have written a code that solves 3n + 1 problem
but when i run it and input (1 200000) i get
Access violation reading location 0x50F9BF08
I don't know what this exception is and I'll be very thankful if someone helps
here's my code:
#include "iostream"
#include "conio.h"
using namespace std;
#define MAX 1000000
long int cycleLengthResult[MAX] = { 0 };
long int cycleLength(long int num)
{
if (num > MAX)
{
if (num % 2 == 0)
return 1 + cycleLength(num / 2);
else
return 1 + cycleLength(3 * num + 1);
}
else if (cycleLengthResult[num] == 0)
{
int count = 0;
if (num == 1)
count = 1;
else if (num % 2 == 0)
count = 1 + cycleLength(num / 2);
else
count = 1 + cycleLength(3 * num + 1);
cycleLengthResult[num] = count;
}
return cycleLengthResult[num];
}
int main()
{
int i, j;
long int max;
while (cin >> i >> j)
{
max = 0;
cout << i << " " << j << " ";
if (i > j)
{
int temp;
temp = j;
j = i;
i = temp;
}
for (int k = i; k <= j; k++)
{
cycleLength(k);
if (cycleLengthResult[k] > max)
max = cycleLengthResult[k];
}
cout << max << endl;
}
_getch();
return 0;
}
There's a pretty good chance you are overrunning the cycleLengthResult array. Certainly the expression in the if (num > MAX) clause is suspicious - if num is odd it will certainly exceed the array boundaries.
One way to figure this out easily is to not use a raw array, but a std::array, and access it not using operator[], but using member function at(). at() has the additional bonus of doing bounds checking for you, so you can see where your function fails.
You are overflowing the limit of the long int. If you would have debugged the code you'd see that the issue happens when you recursively call return 1 + cycleLength(3 * num + 1); with num being 827370449, thus 3 * num + 1 is 2482111348 (which is more than LONG_MAX or 2147483647) and subsequently cycleLength is called with num being -1812855948. You can fix this by using an unsigned value long int cycleLength(unsigned long int num). I did not devote time to look at the actual algorithm but you may be better of with a 64bit value for num if the value grows really big.

Need to calculate series equation converging to π

First time programming and I’ve got to write a program that calculates the series equation
(n!)^2*2^n+1/(2n+1)!, n being the amount of terms the user inputs.
I’ve got it to where the user inputs n and I get the answer for that number only.
How do I make it so that I get the sum of all answers from 0 to the user input?
#include <iostream>
#include<cmath>
using namespace std;
int main()
{
double i,n,factorial,factorial2,n2,a;
a = 1;
cout<<"Enter # of terms:";
cin>>n;
for (i = 0; i <= n; i++)
if (i == 0)
factorial = 1;
else
factorial = factorial * i;
factorial = pow(factorial,2)*pow(2,n+1);
n2 = 2*n+a;
for (i = 0; i <= n2; i++)
if (i == 0)
factorial2 = 1;
else
factorial2 = factorial2 * i;
factorial = factorial/factorial2;
cout<<factorial<<endl;
system("PAUSE");
}
Here's the code from my comments, all laid out to be readable...
#include <iostream>
#include <cmath>
int factorial(int n)
{
return n <= 1 ? 1 : factorial(n - 1) * n;
}
OR if you find that factorial function confusing, SlySherZ suggested this beginner-friendly alternative (you don't want both implementations).
int factorial(int n)
{
if (n <= 1)
return 1;
return factorial(n - 1) * n;
}
Continuing...
double f(double n)
{
return std::pow(fact(n),2) * std::pow(2, n) + 1 / factorial(2 * n + 1);
}
int main()
{
double n, total = 0;
while (std::cin >> n)
total += f(n);
std::cout << "total " << total << '\n';
}
You have two options:
Use a loop that will go through each n;
Make a recursive function:
// In pseudocode
term (n){
if ( n < 0 ) return 0;
// calculate y for this n;
return y + term( n - 1 );
}
A recursive function (assuming you're familiar with functions) is a function that calls itself to solve a problem. For example, n! = (n - 1)! * n. You can use this simple fact an create a factorial function f ( n ) that returns n * f ( n - 1 ) unless n is 1 (returns 1 in this case).
I'll develop the first option:
// I assumed your code is working and that factorial holds the values you want to sum.
// If that's not the case, I believe you can use it to solve your problem anyway
#include <iostream>
#include<cmath>
using namespace std;
int main() {
double n, total = 0;
cout << "Enter # of terms:";
cin >> n;
while (n >= 0) {
double i, factorial, factorial2, n2, a;
a = 1;
for (i = 0; i <= n; i++) {
if (i == 0)
factorial = 1;
else
factorial = factorial * i;
}
factorial = pow(factorial, 2)*pow(2, n + 1);
n2 = 2 * n + a;
for (i = 0; i <= n2; i++) {
if (i == 0)
factorial2 = 1;
else
factorial2 = factorial2 * i;
factorial = factorial / factorial2;
}
total += factorial;
n--;
}
cout << total << endl;
}
Hope it helps :D