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

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.

Related

Why my empty string assignment doesn't clear my string

I have an exercise which looks like that:
Problem statement is simple and straight forward . You will be given a non-negative integer P of length N and you need to check whether
it's divisible by Q ?
Integer P will be given in its decimal representation with P0 as leftmost digit and P1 as second digit from left !
Rest of the digit can be generated from the formula :
Pi = ( 4*Pi-1 + Pi-2 ) modulo Q for 2 <= i <= N-1
Input
The first line contains one integer T - denoting the number of test cases.
T lines follow each containing four integers P0 , P1 , Q and N !
Output
For each testcase output YES if the corresponding integer is divisible by Q and NO otherwise.
Constraints
T <= 100000
0 < P0 , P1 , Q < 10
0 < N <= 1018
Example
Input:
4
1 4 2 2
1 4 2 1
4 2 3 2
3 4 7 3
Output:
YES
NO
YES
NO
Explanation
Value of P is 14, 1, 42, 345 in respective cases !
and that's what I came up with
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
int t, q, n, p_0, p_1, p_temp, p;
vector<int> digits;
vector<string> answers;
string number = "";
cin >> t;
for (int i = 0; i < t; i++)
{
cin >> p_0 >> p_1 >> q >> n;
if (n == 1)
{
digits.push_back(p_0);
}
else
{
digits.push_back(p_0);
digits.push_back(p_1);
for (int i = 2; i <= (n - 1); i++)
{
p_temp = (4 * digits[i - 1] + digits[i - 2]) % q;
digits.push_back(p_temp);
}
}
for (int i = 0; i < digits.size(); i++)
{
number += to_string(digits[i]);
}
p = stoi(number);
cout << number << endl;
if (p % q == 0)
{
answers.push_back("YES");
}
else
{
answers.push_back("NO");
}
number = "";
}
for (int i = 0; i < answers.size(); i++)
{
cout << answers[i] << endl;
}
}
Everything I have done works fine, except for one thing, this part does not clear my number variable
number = "";
And honestly I don't know why, could someone correct my mistakes and explain me what did I do wrong. Thanks.
Your problem is with the digits vector.
Each loop the number string just gets repopulated with the digits vector which is never cleared.
Use digits.clear() to empty the vector like so:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
int t, q, n, p_0, p_1, p_temp, p;
vector<int> digits;
vector<string> answers;
string number = "";
cin >> t;
for (int i = 0; i < t; i++)
{
cin >> p_0 >> p_1 >> q >> n;
if (n == 1)
{
digits.push_back(p_0);
}
else
{
digits.push_back(p_0);
digits.push_back(p_1);
for (int i = 2; i <= (n - 1); i++)
{
p_temp = (4 * digits[i - 1] + digits[i - 2]) % q;
digits.push_back(p_temp);
}
}
for (int i = 0; i < digits.size(); i++)
{
number += to_string(digits[i]);
}
p = stoi(number);
cout << number << endl;
if (p % q == 0)
{
answers.push_back("YES");
}
else
{
answers.push_back("NO");
}
digits.clear();
number = "";
}
for (int i = 0; i < answers.size(); i++)
{
cout << answers[i] << endl;
}
}
To clear a string you can/should use std::string::clear() as:
number.clear();
There may be other logical errors in your program which may be the reason for not getting the output you expect.
Also instead of creating/initializing the string number using string number = "";, you should use
string number;//no need to write = ""

I want to change the condition, but I can't

Problem: Children are taught to add multi-digit numbers from right to left, one digit at a time. Many find the “carry” operation, where a 1 is carried from one digit position to the next, to be a significant challenge. Your job is to count the number of carry operations for each for a set of addition problems so that educators my assess their difficulty.
Input: Each line of input contains two unsigned integers less than 10 digits. The last line of input contains “0 “0.
Input Examples: For each line of input except the last, compute the number of carry operations that result from adding the two numbers and print them in the format shown below.
This is the original code that satisfies inputs which are less than 10 digits
#include <iostream>
#include <cstdio>
#include <cstdlib>
int main(void){
unsigned int n1, n2, remain_n1, remain_n2, carry;
while(1)
{
std::cin >> n1 >> n2;
if(n1 == 0 && n2 == 0)
break;
int carry = 0;
int count = 0;
int sum = 0;
while(n1 != 0 || n2 != 0)
{
remain_n1 = n1 % 10;
remain_n2 = n2 % 10;
if(carry == 1)
remain_n1++;
sum = remain_n1 + remain_n2;
carry = 0;
if(sum >= 10){
carry = carry + 1;
count = count + 1;
}
n1 = n1 / 10;
n2 = n2 / 10;
}
if(count == 0)
std::cout << "No carry operation." << std::endl;
else if(count == 1)
std::cout << count << " " << "carry operation" << std::endl;
else
std::cout << count << " " << "carry operations" << std::endl;
}
return 0;
}
The problem input says less than 10 digits, but I want to change to satisfy the condition whatever input comes. And this is my code. How should I fix this?
std:;string n1, n2;
while(1){
std:;cint >> n1 >> n2;
if(n1 == "0" && n2 == "0")
break;
int max_len = n1.szie();
if (max_len < n2.size())
max_len = n2.size();
int nn1[max_len] - {0);
int nn2[max_len] = {0};
for(int i = 0; i < n1.size(); i++)
nn1[max_len - n1.size() + i]; = n1[i] - '0';
}
You don't need any extra storage for numbers, you can use the strings' digits directly and convert as you go.
Something like this, perhaps:
std::cin >> a >> b;
int carry = 0;
int count = 0;
// Iterate in reverse.
for (auto ia = a.rbegin(), ib = b.rbegin(); ia != a.rend() && ib != b.rend(); ++ia, ++ib)
{
int sum = (*ia - '0') + (*ib - '0') + carry;
carry = sum >= 10;
count += carry;
}

Wrong Solution if Memoization is added to Recursion

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;

the biggest common divisor of 2 numbers using arrays

How could I find the biggest common divisor of 2 numbers using array? I tried to solve it using 2 arrays and I couldn't finish it. How could I improve this program?
#include <iostream>
using namespace std;
int main()
{
unsigned int A[2][10], B[2][10], a, b, c_exp, d, i1, P, x;
bool apartine = false;
cout << "a="; cin >> a;
cout << "b="; cin >> b;
P = 1;
c_exp = 0;
i1 = 0;
while (a % 2 == 0)
{
c_exp++;
a = a/2;
}
if (c_exp != 0)
{
A[i1][0] = 2;
A[i1][1] = c_exp;
i1++;
}
d = 3;
while (a != 1 && d <= a)
{
c_exp=0;
while (a % d == 0)
{
c_exp++;
a = a/d;
}
if (c_exp!=0)
{
A[i1][0] = d;
A[i1][1] = c_exp;
i1++;
}
d = d+2;
}
cout << "\nMatricea A contine:";
for (int i = 0; i < i1; i++)
{
cout << "\n";
for (int j = 0; j < 2; j++)
cout << A[i][j] << ",";
}
c_exp = 0;
i1 = 0;
while (b % 2 == 0)
{
c_exp++;
b = b/2;
}
if (c_exp != 0)
{
B[i1][0] = 2;
B[i1][1] = c_exp;
i1++;
}
d = 3;
while (b != 1 && d <= b)
{
c_exp = 0;
while (b % d == 0)
{
c_exp++;
b = b/d;
}
if (c_exp != 0)
{
B[i1][0] = d;
B[i1][1] = c_exp;
i1++;
}
d = d+2;
}
cout << "\nMatricea B contine:";
for (int i = 0; i < i1; i++)
{
cout << "\n";
for (int j = 0; j < 2; j++)
cout << B[i][j] << ",";
}
return 0;
}
From now on I have to find if the first number of first array exist in the second array and after this I have to compare the exponents of the same number of both array and the lowest one I have to add it to product. After this I have to repeat the same proccess with the second number to the last one of the first array. The problem is that I don't know how to write this.I have to mention that this program isn't complete.
Any ideas?
If you need better solution then you can avoid array and use the below logic.
int main()
{
int a =12 ,b = 20;
int min = a>b ? a:b; // finding minimum
if(min > 1)
{
for (int i=min/2; i>1; i--)//Reverse loop from min/2 to 1
{
if(a%i==0 && b%i==0)
{
cout<<i;
break;
}
}
}
else if(min == 1)
{
cout<<"GCD is 1";
}
else
cout<<"NO GCD";
return 0;
}
You can also check the working example Greatest Common Divisor
I am not quite sure what you are trying to achieve with your code. It looks over complicated. If I were to find the biggest common divisor of two numbers I would do something like the following:
## This is not a correct implementation in C++ (but close to it) ##
Read the two integers **a** and **b**
int max_div(int a, int b){
int div = a > b ? a : b;
while (div != 1 && (a%div != 0 && b%div != 0)){
div--;
}
return div;
}
This function starts with the minimum of a and b as the highest possible common divisor and then works its way backwards until one of two possible outcomes:
It finds a common divisor (a%div == 0 and b%div == 0)
It reaches one (always a common divisor)
EDIT : Now returns one if no higher divisor is found. (Was returning zero which made no sense)

Adding binary numbers in C++

How would I add two binary numbers in C++? What is the correct logic?
Here is my effort, but it doesn't seem to be correct:
#include <iostream>
using namespace std;
int main()
{
int a[3];
int b[3];
int carry = 0;
int result[7];
a[0] = 1;
a[1] = 0;
a[2] = 0;
a[3] = 1;
b[0] = 1;
b[1] = 1;
b[2] = 1;
b[3] = 1;
for(int i = 0; i <= 3; i++)
{
if(a[i] + b[i] + carry == 0)
{
result[i] = 0;
carry = 0;
}
if(a[i] + b[i] + carry == 1)
{
result[i] = 0;
carry = 0;
}
if(a[i] + b[i] + carry == 2)
{
result[i] = 0;
carry = 1;
}
if(a[i] + b[i] + carry > 2)
{
result[i] = 1;
carry = 1;
}
}
for(int j = 0; j <= 7; j++)
{
cout<<result[j]<<" ";
}
system("pause");
}
Well, it is a pretty trivial problem.
How to add two binary numbers in c++. what is the logic of it.
For adding two binary numbers, a and b. You can use the following equations to do so.
sum = a xor b
carry = ab
This is the equation for a Half Adder.
Now to implement this, you may need to understand how a Full Adder works.
sum = a xor b xor c
carry = ab+bc+ca
Since you store your binary numbers in int array, you might want to understand bitwise operation.
You can use ^ for XOR,| operator for OR, & operator for AND.
Here is a sample code to calculate the sum.
for(i = 0; i < 8 ; i++){
sum[i] = ((a[i] ^ b[i]) ^ c); // c is carry
c = ((a[i] & b[i]) | (a[i] & c)) | (b[i] & c);
}
Since you were asking about C++, you deserve a C++ answer. Use bitsets:
#include <bitset>
#include <iostream>
int main() {
std::bitset<5> const a("1001");
std::bitset<5> const b("1111");
// m here is a mask to extract the lsb of a bitset.
std::bitset<5> const m("1");
std::bitset<5> result;
for (auto i = 0; i < result.size(); ++i) {
std::bitset<5> const diff(((a >> i)&m).to_ullong() + ((b >> i)&m).to_ullong() + (result >> i).to_ullong());
result ^= (diff ^ (result >> i)) << i;
}
std::cout << result << std::endl;
}
This works for arbitrarily long bit sets.
You could use "Bitwise OR" operation to reduce the code since
1 or 1 = 1
1 or 0 = 1
0 or 1 = 1
0 or 0 = 0
You could also convert both number to decimal sum and them go back to binary again.
Converting decimal to binary
int toBinary (unsigned int num, char b[32])
{
unsigned int x = INT_MIN; // (32bits)
int i = 0, count = 0;
while (x != 0)
{
if(x & num) // If the actual o bit is 1 & 1 = 1 otherwise = 0
{
b[i] = '1';
count++;
}
else b[i] = '0';
x >>=1; // pass to the left
i++;
}
return count;
}
There is a bug :
if(a[i]+b[i]+carry==1)
{
result[i]=1;
carry=0;
}
Also u might want to print in reverse
for(int j=6; j>=0; j--)
{
cout<<result[j]<<" ";
}
Your arrays are one item too small for your indexing.
int a[3] only has 3 elements, so a[3] = 1 is invalid (it has undefined behaviour) since it's accessing the 4th element, which doesn't exist.
Likewise for the other arrays.
That means that the whole program has undefined behaviour, i.e. it can do anything or nothing at all.
(What's probably happening in your case is that writing outside the arrays is overwriting the other variables.)
You're also not initialising the result array, so its content is just some random data.
Since you only update 4 of its elements but print all of them (and more), the output will be random data as well.
Following were the errors in your code and fixed code is also below"
int a[] was of size 3 so it cannot store at the 3rd index. use int a[4].
if(a[i]+b[i]+carry==1) wrong values were assigned in this check update result[i]=1; carry=0.
The sequence of checks is reversed.
The last carry was not stored in the result.
The addition result stored in the result array was in reverse order so printed it in reverse.
here is the working piece of code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int a[4];
int b[4];
int carry=0;
int result[5];
a[0]=1;
a[1]=0;
a[2]=0;
a[3]=1;
b[0]=1;
b[1]=1;
b[2]=1;
b[3]=1;
for(int i=0; i<4; i++)
{
if(a[i]+b[i]+carry==3)
{
result[i]=1;
carry=1;
}
if(a[i]+b[i]+carry==2)
{
result[i]=0;
carry=1;
}
if(a[i]+b[i]+carry==1)
{
result[i]=1;
carry=0;
}
if(a[i]+b[i]+carry==0)
{
result[i]=0;
carry=0;
}
}
result[4]=carry;
for(int j=4; j>=0; j--)
{
cout<<result[j];
}
cout<<endl;
return 0;
}
#include <stdio.h>
int main()
{
long binary1, binary2;
int i = 0, remainder = 0, sum[20];
printf("Enter the first binary number: ");
scanf("%ld", &binary1);
printf("Enter the second binary number: ");
scanf("%ld", &binary2);
while (binary1 != 0 || binary2 != 0)
{
sum[i++] =(binary1 % 10 + binary2 % 10 + remainder) % 2;
remainder =(binary1 % 10 + binary2 % 10 + remainder) / 2;
binary1 = binary1 / 10;
binary2 = binary2 / 10;
}
if (remainder != 0)
sum[i++] = remainder;
--i;
printf("Sum of two binary numbers: ");
while (i >= 0)
printf("%d", sum[i--]);
getch();
return 0;
}
Repeatedly do
(x, y) <- ((x & y) << 1, x ^ y)
until x is 0. y is the answer.
you should do this
for(int i = 3; i >= 0; i--)
{
if(a[i] + b[i] + carry == 0)
{
result[i] = 0;
carry = 0;
}
else if(a[i]+b[i]+carry==1)
{
result[i]=1;
carry=0;
}
else if(a[i] + b[i] + carry == 2)
{
result[i] = 0;
carry = 1;
}
else if(a[i] + b[i] + carry > 2)
{
result[i] = 1;
carry = 1;
}
printf("%d",result[i]);
}
A non-conventional solution, but it works:
int main() {
int A[] = { 0, 0, 0, 1, 1, 0, 1, 0};
int B[] = { 0, 0, 0, 0, 1, 1, 0, 0};
int size = sizeof(A)/sizeof(*A);
int C[size+1];
int t = 0;
for(int i = size-1; i > -1; i--){
C[i+1] = A[i]+B[i]+t;
t = C[i+1]/2;
C[i+1] %= 2;
}
C[0] = t;
}
What if their sizes are not the same? Also, you would want to allow the user to input the binary numbers (in this case representing integers) as integers and not as elements of arrays. Here is a piece of code that accomplishes those :-)
#include <iostream>
using namespace std;
// Add two numbers in binary
void sumBinary(int num1, int num2, int* sum12){
int mod1 = 0;
int mod2 = 0;
int carry = 0;
int factor = 1;
int flag = 0;
*sum12 = 0;
while (!flag){
mod1 = num1 % 10;
mod2 = num2 % 10;
num1 /= 10;
num2 /= 10;
if ((carry + mod1 + mod2) == 2){
*sum12 += 0;
carry = 1;
}
else if ((carry + mod1 + mod2) == 3){
*sum12 += factor;
carry = 1;
}
else if ((carry + mod1 + mod2) == 0){
*sum12 += 0;
carry = 0;
}
else{
*sum12 += factor;
carry = 0;
}
factor *= 10;
if ((num1 == 0) && (num2 == 0)){
*sum12 += carry*factor;
flag = 1; }
}
}
void main(){
int num1, num2, sum12;
cout << "Enter the first binary integer number: ";
cin >> num1;
cout << "Enter the second binary integer number: ";
cin >> num2;
sumBinary(num1, num2, &sum12);
cout << "The sum in binary form is :" << sum12 << endl;
}
A simple way :
int getBit(string s, int index)
{
if(index >= 0) return (s[index] - '0');
else return 0;
}
string addBinary(string a, string b)
{
if(a.size() > b.size()) while(a.size() > b.size()) b = "0" + b;
else if(b.size() > a.size()) while(b.size() > a.size()) a = "0" + a;
int l = max(a.size()-1, b.size() - 1);
string result = "";
int s=0;
while(l>=0 || s==1)
{
s += getBit(a, l) + getBit(b, l) ;
result = char(s % 2 + '0') + result;
s /= 2;
l--;
}
return result;
}
int main(){
ios::sync_with_stdio(0); cin.tie(0);
int num1=12, num2=45, sum=0;
bool b1, b2, carry=0;
for(int i=0;i<32;i++){
b1=( 1<<i ) & num1;
b2=( 1<<i ) & num2;
sum = (b1 ^ b2 ^ carry) ? sum ^ (1<<i) : sum;
carry = ((b1 & b2) | (b1 & carry) | (b2 & carry));
}
cout<<sum;
return 0;
}
Easy to understand code
Add Two Binary Numbers (input datatype = int)
#include <iostream>
using namespace std;
int power(int a, int b)
{
int ans = 1;
while (b)
{
ans *= a;
b--;
}
return ans;
}
int main()
{
int n1, n2, carry = 0, ans = 0, rem1, rem2, remsum = 0, i;
cout << "Enter First Number : ";
cin >> n1;
cout << "Enter Second Number : ";
cin >> n2;
for (i = 0; n1 != 0 || n2 != 0; i++, n1 /= 10, n2 /= 10)
{
rem1 = n1 % 10;
rem2 = n2 % 10;
remsum = rem1 + rem2 + carry;
if (remsum == 2)
{
carry = 1;
remsum = 0;
}
else if (remsum == 3)
{
carry = 1;
remsum = 1;
}
else if (remsum == 0)
{
carry = 0;
remsum = 0;
}
else if (remsum == 1)
{
carry = 0;
remsum = 1;
}
ans = remsum * power(10, i) + ans;
}
ans = carry * power(10, i) + ans;
cout << ans;
return 0;
}