Friday, December 20, 2013

C/C++ bitwise operators, gcd(greatest common divisor) algorithm, codechef RECIPE - "cutting recipe" problem guidance and solution

codechef RECIPE - "cutting recipe" problem: http://www.codechef.com/problems/RECIPE

guidance: http://discuss.codechef.com/questions/4201/recipe-editorial

imho, we(including myself) have to learn Euclid's algorithm: http://en.wikipedia.org/wiki/Euclid%27s_algorithm
and there they talk of bitwise operators -  "<<", ">>",  "->", "&" and "XOR", stuff which i havent learnt yet. so, lets begin with that "<<", ">>" - left shift and right shift in C/C++ languages. for them have a look at:
1 - http://en.wikipedia.org/wiki/Bitwise_operations_in_C
2 - http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fbitshe.htm
3 - http://www.c4learn.com/c-programming/c-bitwise-right-shift/
4 - http://www.cprogramming.com/tutorial/bitwise_operators.html
now, i suppose you have learnt C/C++ bitwise operators and lets move on to Euclidean or gcd(greatest common divisor) algorithm. i liked binary gcd algorithm much, here it is: http://en.wikipedia.org/wiki/Binary_GCD_algorithm

my c++ solution to codechef RECIPE - "cutting recipe" problem: http://ideone.com/m3Lebc
#include <iostream>
#include <algorithm>
using namespace std;

unsigned int gcd(unsigned int u, unsigned int v)
{
    // simple cases (termination)
    if (u == v)
        return u;

    if (u == 0)
        return v;

    if (v == 0)
        return u;

    // look for factors of 2
    if (~u & 1) // u is even
    {
        if (v & 1) // v is odd
            return gcd(u >> 1, v);
        else // both u and v are even
            return gcd(u >> 1, v >> 1) << 1;
    }

    if (~v & 1) // u is odd, v is even
        return gcd(u, v >> 1);

    // reduce larger argument
    if (u > v)
        return gcd((u - v) >> 1, v);

    return gcd((v - u) >> 1, u);
}

int main() {
int t, n, arr[50], cmmn, yes;
cin>>t;
while(t--) {
cin>>n;
for(int i=0; i<n; i++) cin>>arr[i];
cmmn=1005; yes=1;
for(int i=1; i<n; i++) if(gcd(arr[0], arr[i])<cmmn) cmmn=gcd(arr[0], arr[i]);
for(int i=0; i<n; i++) if(cmmn!=arr[i]) yes=0;
if(yes) for(int i=0; i<n; i++) cout<<1<<" ";
else if(cmmn==1) for(int i=0; i<n; i++) cout<<arr[i]<<" ";
else for(int i=0; i<n; i++) cout<<(arr[i]/cmmn)<<" ";
cout<<endl;
}
return 0;
}

note on  my code: the gcd block is taken from wiki url i have shown above. and main block is my c++ code. i initialised arr of 50 ingredients and saved ingredients in it. and then i have taken cmmn - the greatest common divisor for ingredients in the array. if cmmn==1 then the array has no gcd, so i just printed out the arr itself. if cmmn is equal to ingredients of arr then yes==1, which means that all ingredients in the arr are same numbers,  for ex 4 as given in the codechef sample output, if so i printed out 1 for every ingredient of  arr. and if there exist gcd(here cmmn) other than 1 and ingredints itself, then print out arr[i]/cmmn. that is it.

NOTE: i still have difficulty in understanding the binary gcd algo. can anyone pls post the easier way to learn binary gcd algo. tnx

No comments:

Post a Comment