Sum of two squares decomposition counting - c++

I want to count how many pairs of natural number there are such that a2 + b2 = c2. As an input to my function I have c.
My idea was to first check whether the condition is fulfilled, than if not, I wanted to have a loop iterating desired expression up to c. If result is equal to the square of c than I wanted to have count++. Question is why this is not working?
Some corrections added.
int sum(int c) {
int b=1;
int a=1;
int count=0;
int result;
if (a*a + b*b != c*c)
{
for (int i=1; i<=c; i++)
{
b=i;
result = a*a + b*b;
if (result == c*c)
count++;
}
a++;
}
else
count++;
return count;
}
The problem is I still do not understand why this does not want to work.
My second idea was to approach it with while loop:
int sum(int c) {
int b=1;
int a=1;
int count=0;
int result;
if (a*a + b*b != c*c)
{
while(b<=c)
{
result = a*a + b*b;
if (result == c*c)
{count++;
b++;
}
else
b++;
}
a++;
}
else
count++;
return count;
}
Not working as well.
Anybody any ideas as to how to make it work? Any of those two versions? Maybe hints?

The problem is that you're using an if expecting it to work like a loop. At the bottom of the if you're incrementing a, however because it is an if and not a while or for, it doesn't jump back up to the top.
Both a and b need to change, so you need a loop to control each one.
for (a=1; a<=c; a++) {
for (b=a; b<=c; b++) {
if (a*a + b*b == c*c) {
count++;
}
}
}
Note that b starts at the current value of a instead of 1. That way, you aren't trying the same pair of numbers (just switched) twice.

Related

What is explanation for this FOR-IF loop?

I am writing a code for GCD in C++ but I am encountering a mysterious error that I can't seem to think of its probable reason.
In the below program if both the numbers are equal to i ... it will break and return the value of i.
But it doesn't seems to work because it outputs the result as 1.
int gcd2(int a, int b) {
int i,hcf=0;
if (b > a) {
a = a + b;
b = a - b;
a = a - b;
}
for (i = 1; i <= b; ++i) {
if (a % i == 0 && b % i == 0) {
break;
}
}
return i;
}
But when I add a variable HCF in the same code :
int gcd2(int a, int b) {
int i,hcf=0;
if (b > a) {
a = a + b;
b = a - b;
a = a - b;
}
for (i = 1; i <= b; ++i) {
if (a % i == 0 && b % i == 0) {
hcf = i;
}
}
return hcf;
}
It works. Why is that? Can anyone clarify?
The variable hfc is not the cause for the difference you notice. If we keep the difference but introduce a hfc in both versions we have:
int hfc = 0;
for (i = 1; i <= b; ++i) {
if (some_condition(i)) {
hfc = i;
break; // breaks out of the loop
}
}
return hfc;
vs
int hfc = 0;
for (i = 1; i <= b; ++i) {
if (some_condition(i)) {
hfc = i; // no break !!!
}
}
return hfc;
The first returns the first value of i for which some_condition(i) is true. The second version returns the last value of i for which some_condition(i) is true. This and the fact that any number is divisible by 1 explains the different results you get.
The simple difference between your two samples is whether the loop goes through the whole interval and whether the first or last match is returned.
Using break makes it to stop when the first number fulfilling the condition is found. As commenters note, 1 is the divider of all numbers, so you should rather have started with i = 2. However, this variant still won’t find the greatest common divisor in all cases.
On the other hand, the variable assignment can be called multiple times, so your second sample returns the last, i.e. greatest number found which is most likely your desired result.

GCD of Multiple Number

I know how to write a code finding a GCD of 2 number . However, I am trying to solve a problem of finding a GCD of n number and I think the algorithm is a little bit different than using an Eucledian algorithm. My code can be compiled , but it always gave me the wrong result. For example when i put n = 2 , GCD of 16 and 12 it gave the answer 8. Here is my code :
#include<iostream>
using namespace std;
int main()
{
int a,b[100],c,d,e=0;
cin>>a;
for(c=0 ; c<a ; c++)
{
cin>>b[c];
}
for(c=0 ; c<a-1 ; c++)
{
if(c < 1)
{
d = b[c];
}
if(b[c] < d)
{
d = b[c];
}
}
while(d>0)
{
for(c=0 ; c<a ; c++)
{
if(b[c] % d < 1)
{
e++;
}
}
if(e == c)
{
cout<<d;
break;
}
d--;
}
}
Can you guys please find the mistake in my code?
Your code does not compute the greatest common divisor of the input array - it counts how many of the entries are evenly divisible by the smallest element d of the array, then how many are divisible by one smaller, and so on until d is 0. This has nothing to do with the GCD at all.
One easy way - though not necessarily the fastest - would be based on the fact that the GCD of three numbers must be the same as the GCD of any one of those numbers and the GCD of the other two.
gcd(a, b, c) = gcd(gcd(a, b), c) = gcd(a, gcd(b, c)) = gcd(gcd(a, c), b)
Extension to n inputs is elementary:
int result = a[0];
for (int i = 1; i < a.Length; ++i)
result = gcd(result, a[i]);
Code for the GCD of two numbers can be found all over the 'net, for example at Rosetta Code. One of my favourites is this plain iterative version:
int gcd (int a, int b)
{
while (b)
{
int t = b;
b = a % b;
a = t;
}
return a;
}
C# allows a more succinct formulation but in other languages this probably won't work (in C++ it would invoke undefined behaviour, for example):
static int gcd (int a, int b)
{
while (b != 0)
b = a % (a = b);
return a;
}
In case some find it helpful, here is an implementation of the Euclidean algorithm in JavaScript.
function EuclideanGCD(a, b) {
// Make sure a > b, interchange values
if (a < b) {
c = a;
a = b;
b = c
}
// If A = 0 then GCD(A,B) = B and we can stop.
if (a == 0) {
return b;
// If B = 0 then GCD(A,B) = A and we can stop.
} else if (b == 0) {
return a;
} else {
let gdc = 0;
let quotient = Math.floor(a / b); // Get the divisor
let remainder = a % b; // Get the remainder
// Make a recursive call, till we hit 0
gdc = EuclideanGCD(b, remainder);
return gdc;
}
}
var gcd = EuclideanGCD(234, 357);
console.log(gcd); // Outputs: 3

How do I solve this p‌r‌o‌b‌l‌e‌m using Dynamic Programming Top Down approach?

I'm trying to solve a problem from Codeforces (http://codeforces.com/problemset/problem/189/A)
Here's the problem statement:
Polycarpus has a ribbon, its length is n. He wants to cut the ribbon in a way that fulfils the following two conditions:
After the cutting each ribbon piece should have length a, b or c.
After the cutting the number of ribbon pieces should be maximum.
Help Polycarpus and find the number of ribbon pieces after the required
cutting.
Input
The first line contains four space-separated integers n, a, b and c (1 ≤ n, a, b, c ≤ 4000) — the length of the original ribbon and the acceptable lengths of the ribbon pieces after the cutting, correspondingly. The numbers a, b and c can coincide.
Output
Print a single number — the maximum possible number of ribbon pieces. It is guaranteed that at least one correct ribbon cutting exists.
Sample Input
5 5 3 2
Sample Output
2
I tried to solve this problem using Dynamic Programming (Topdown approach). But I'm not able to get the correct answer. There might be something wrong with the recursive function. Here's my code:
#include<bits/stdc++.h>
using namespace std;
int n,s;
int a[3];
int val,m=-1;
int dp(int n)
{
if(n==0)
return 0;
for(int i=0;i<3;i++)
{
if(n>=a[i])
{
val=1+dp(n-a[i]);
}
}
if(val>m)
m=val;
return m;
}
int main()
{
scanf("%d %d %d %d",&n,&a[0],&a[1],&a[2]);
cout<<dp(n)<<endl;
return 0;
}
What is the problem in the above approach?
There are several problems:
Wrong Search
In your lines
for(int i=0;i<3;i++)
{
if(n>=a[i])
{
val=1+dp(n-a[i]);
}
}
if(val>m)
m=val;
You should be checking for the maximum of the different vals obtained for the different choices of i.
Wrong Termination
If the length is not 0 and no ribbon can be cut, you should return something like minus infinity. You currently return m which is initially -1 (more on this later). This is wrong, and for long ribbons will essentially ensure that you just choose the minimum of a, b, and c.
Use of Globals
Some globals, e.g., m are initialized once but are modified by the recursion. It's not "just" bad programming habits - it's not doing what you want.
No Reuse
By calling the recursion unconditionally, and not reusing previous calls, your running time is needlessly high.
int main() {
int n, a, b, c;
scanf("%d %d %d %d", &n, &cuts[0], &cuts[1], &cuts[2]);
sort(cuts, cuts + 3);
for (int i = 0; i <= n; i++) {
max_cuts[i] = INT_MIN;
}
max_cuts[0] = 0;
max_cuts[cuts[0]] = 1;
max_cuts[cuts[1]] = 1;
max_cuts[cuts[2]] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < 3; j++) {
if (cuts[j] > i) break;
max_cuts[i] = max(max_cuts[i - cuts[j]] + 1, max_cuts[i]);
}
}
printf("%d\n", max_cuts[n]);
return 0;
}
#Ami Tavory correctly suggested the problems with your recursive approach. May be my solution below can help you understand better how to form states and check bounds:
int main()
{
int n, a, b, c;
cin >> n >> a >> b >> c;
const int l = n + 1;
int sum[l];
fill(sum, sum+l, INT_MIN);
sum[0] = 0;
for(int i=1; i<=n; i++)
{
if(i - a >= 0)
{
sum[i] = sum[i-a] + 1;
}
if(i - b >= 0 && sum[i-b] + 1 > sum[i])
{
sum[i] = sum[i-b] + 1;
}
if(i - c >= 0 && sum[i-c] + 1 > sum[i])
{
sum[i] = sum[i-c] + 1;
}
}
cout << sum[n] << endl;
return 0;
}
Simply at each sum[i], we are maximizing the number of cuts. So, at sum[i], we are storing the max(sum[i-a]+1, sum[i-b]+1, sum[i-c]+1).
Other than this, there are just bound checks.
you can solve this problem through top down approach.A dp problem always check all the possible cases then gives us the optimal solution.so here is the code
#include<bits/stdc++.h>
using namespace std;
int a,b,c;
int DP[4001];
int solve(int n){
if(n == 0)return 0;
if(n<0) return INT_MIN;
if(DP[n] != -1)return DP[n];
else{
DP[n] = max(1+solve(n-a),max(1+solve(n-b),1+solve(n-c)));
return DP[n];
}
}
int main(){
int n,x;
cin>>n>>a>>b>>c;
for(int i = 0;i<4001;++i){
DP[i] = -1;
}
x = solve(n);
cout<<x;
}

Is there a way to ignore elements in an array without changing the array in a recursive function?

I'm trying to write a recursive function that checks if two arrays have the same elements even if they aren't sorted, but I I can't change the arrays and I can't copy them or use a third/fourth arrays and it has to be recursive, lastly, I can't change the signature of the function.
So now I have to get rid of overwrite(A2, len, i); because that's destroying A2, but I don't see any way to do it and still have a working function... can I have a hint on how to do it? Maybe there's a way to save the elements of A2 by swapping them and then by the end of the recursion to restore them?
In short the algorithm below does a linear search of the last element of A1 in A2, if it's found, overwrite it and continue, this is done so the algorithm won't pick the same element twice, reaching the stopping condition means all the elements are there thus it will return true, otherwise will return false.
bool foo(int A1[], int A2[], int len){//both arrays are size len
int i;
bool found = false;
if (len == 0)return true;//stopping condition for recursion
else{
for (i = 0; i < len && !found; i++)//linear search
if (A1[len - 1] == A2[i]){
overwrite(A2, len, i);//this function shifts back the whole array
found = true;
}
if (found == false) return false;
else foo(A1, A2, len - 1);
}
}
Sample i/o:
A1: 3 2 1
A2: 1 2 3
True
A1: 3 2 3
A2: 1 2 3
False
A solution could be:
find what is the maximum value M in in A1 and how many times it appears
check if it's the same for A2, including the count
find what is the maximum value M1 among all values smaller than M and how many times is present in A1
check if it's the same for A2, including the count
find what is the maximum value M2 among all values smaller than M1 and how many times is present in A1
check if it's the same for A2, including the count
repeat this way until the counter for A1 and A2 is zero or is different
in code:
bool checkSame(int *A1, int *A2, int len) {
struct Same {
static bool check(int *A1, int *A2, int len, int limit) {
int index1=-1, count1=0;
for (int i=0; i<len; i++) {
if (A1[i] <= limit) {
if (index1==-1 || A1[i] > A1[index1]) {
index1 = i;
count1 = 1;
} else if (A1[i] == A1[index1]) {
count1++;
}
}
}
int index2=-1, count2=0;
for (int i=0; i<len; i++) {
if (A2[i] <= limit) {
if (index2==-1 || A2[i] > A2[index2]) {
index2 = i;
count2 = 1;
} else if (A2[i] == A2[index2]) {
count2++;
}
}
}
if (index1 == -1 && index2 == -1) return true;
if (count1 != count2 || count1 == 0 ||
A1[index1] != A2[index2]) return false;
return check(A1, A2, len, A1[index1]-1);
}
};
return Same::check(A1, A2, len, INT_MAX);
}
This algorithm is O(n^2) in time (worst case: arrays are identical and all values unique) and requires constant space if the compiler supports tail call optimization.
The following is a chart for the time needed in ms from 0 to 3000 elements on my PC.
Note that however all this is not a decent solution for the problem but just an exercise in futility. A real solution of course would need more context as there are different criteria for optimality, but I'd probably go for a closed hash table... adding elements while processing A1 and removing elements processing A2 (the removal will fail at some point if and only if the arrays are different):
bool checkSame2(int *A1, int *A2, int len) {
std::vector<int> ht(len, -1), next(len, -1);
for (int i=0; i<len; i++) {
int k = (unsigned)A1[i]*69069 % len;
next[i] = ht[k]; ht[k] = i;
}
for (int i=0; i<len; i++) {
int k = (unsigned)A2[i]*69069 % len;
int prev=-1,p=ht[k];
while (p!=-1 && A1[p] != A2[i]) {
prev = p; p = next[p];
}
if (p == -1) return false;
if (prev == -1) ht[k] = next[p]; else next[prev] = next[p];
}
return true;
}
The execution time for this solution is the purple line touching the N axis in the previous chart (hard to tell with this scale but it's linear + noise, as expected).
Just out of curiosity I also tried what would be the solution if "optimal" means just getting something working that is not hideous:
bool checkSame3(int *A1, int *A2, int len) {
std::map<int, int> counts;
for (int i=0; i<len; i++) counts[A1[i]]++;
for (int i=0; i<len; i++) {
if (--counts[A2[i]] < 0) return false;
}
return true;
}
and this is, unsurprisingly, about 30-40 times slower than the hand-coded hash table version on my PC (but of course still much faster than the recursive version).
Here is a solution that works given all your requirements. It rearranges the arrays, and then un-rearranges them. It uses recursion, uses no additional arrays, and does not change the function signature.
bool foo(int A1[], int A2[], int len){
int i;
if (len == 0){
return true;
} else {
for (i = len - 1; i >= 0; i--){
if (A1[len - 1] == A2[i]){
A2[i] = A2[len - 1];
A2[len - 1] = A1[len - 1];
bool result = foo(A1, A2, len - 1);
A2[len - 1] = A2[i];
A2[i] = A1[len - 1];
return result;
}
}
return false;
}
}
If you are allowed to temporarily change the arrays, provided that you restore them before the last recursive call has returned, you can swap the matching element in A2 with the element at index len - 1 before the recursive call, and swap them back afterwards. Since the recursive call will only look at the index range 0 through len - 2, the matching element will not be considered.

Using one-dimesional array in recursion

Recently I've been working on partition problem. I've done a research and I found that it can be solved using an algorithm on wiki page. Here's the pseudo algorithm:
INPUT: A list of integers S
OUTPUT: True if S can be partitioned into two subsets that have equal sum
1 function find_partition( S ):
2 N ← sum(S)
3 P ← empty boolean table of size (\lfloor N/2 \rfloor + 1) by (n + 1)
4 initialize top row (P(0,x)) of P to True
5 initialize leftmost column (P(x, 0)) of P, except for P(0, 0) to False
6 for i from 1 to \lfloor N/2 \rfloor
7 for j from 1 to n
8 P(i, j) ← P(i, j-1) or P(i-S[j-1], j-1)
9 return P(\lfloor N/2 \rfloor , n)
Using recursion you can calculate if certain sum from integers in array can be reached, if it can be reached it returns true. I start with sumOfTheIntegers/2 and I go back to 0, until I find a solution. When I found the biggest possible sum of the integers that is lower or equal to the average I calculate the difference between the the 2 groups of integers with (average-lowestSumLowerorEqualtoAverage)*2.
But then I confront with problem how can I include one dimensional array in the recursion?
Here's the code, it should probably work, but I haven't tested it yet, because of the problem. So maybe the code contains small errors. But that's not the problem, I'll fix it later.
#include <iostream>
#include <cmath>
using namespace std;
bool matrix (int a, int b)
{
if(b == -1) return true;
else if (a == -1) return false;
else if(matrix(a-1, b) == true) return true;
else if(matrix(a-1,b-numbers[a-1]) == true) return true;
else return false;
}
int main()
{
int number, sum = 0;
cin >> number;
int numbers[number];
for(int i = 0; i<number; i++)
{
cin >> numbers[i];
sum += numbers[i];
}
double average = sum/2.0;
for(int i = floor(sum/2); i!= 0; i--)
{
if(matrix(number+1, i) == true)
{
cout << abs(average-i)*2;
break;
}
}
return 0;
}
The easiest (but certainly not the best) way is to introduce a global variable:
#include <vector>
std::vector<int> numbers;
/* ... */
int main(){
int number;
cin >> number;
numbers.resize(number);
/* ... */
}
Another possibility is to use an additional parameter:
bool matrix (int a, int b, const std::vector<int>& numbers)
{
if(b == -1) return true;
else if (a == -1) return false;
else if(matrix(a-1, b,numbers) == true) return true;
else if(matrix(a-1,b-numbers[a-1],numbers) == true) return true;
else return false;
}
Note that int numbers[number] is actually using a compiler-specific extension (VLA) and is not part of the C++ standard (see Does C++ support Variable Length Arrays? and Why aren't variable-length arrays part of the C++ standard?).
Pass it as an argument to the function
bool matrix (int a, int b, int num_arr[])
{
...
matrix(a-1,b,num_arr);
...
}