This blog is about anything technically opensource or copyleft-ed/ GPL-ed, obviously most of it Linux or connected to Linux in some way.

Wednesday, July 17, 2013

My trouble with Cats

I've struggled a lot with Cats, with multiple codes and submits, across a huge time period, with a wide range of WAs and TLs. The latter is the major part of the problem, that needed a different approach to solving. After getting value of n, my code is pretty simple. I tried getting n by:

  • pow(): this failed since pow(5, 2) gave me 24 and I got a shock of my life... great learning though. :)
  • multiple loops: w and h are worker cats and height of initial cat given in input. tempW and tempH are temporary copies of these to work with in the loop. Outer while loop checks that both w and n are divisible by "potential" n & n+1 respectively. If they are, then the inner two for() loops check that w is the same power of "potential" n as h is a power of "potential" n+1. This check is by i == j at the end of the following code, meaning both have same depth (so that when the height of cats reduces to one from given height, the cats would have reached the given number of worker cats). As simple as that. It all works fine with all the test cases I could find online. Unfortunately, I didn't generate the highest number that int can go to, to test, perhaps thats why I get a TL! Commented it out.
 /*            while(n++) {
                if(w%n || h%(n+1))
                   continue;
                //cout << "n= " << n << endl;
                m = 2;
                tempW = 1;
                for(i= 0; tempW < w; i++) {
                    tempW *= n;
                }
                if(tempW != w)
                    continue;
                tempH = 1;
                cout << i << endl;
                for(j = 0; tempH < h; j++)
                    tempH *= (n + 1);
                if(tempH != h)
                    continue;
                //cout << j << endl;
                if(i == j)
                    break;
            }
*/
  • logarithms: I gave up the above and went exponential via logarithms. :) Now, I am bad at math... so, I'd to read up how logs work and look into some code. I worked the below given beautiful three line code manually through a calculator understanding how it works... and then, voila, Judge gave an AC!! This simple method of using the loghw, "logarithmic ratio of h to w" as a perfect guide for the ratio of their respective factors n+1 and n to have, is sheer beauty! You just have to see that the difference between the two ratios is 0 (or so close to zero, as in < 1^-10). I have worked through some examples of n w.r.t. loghw, and saw that as the "potential" n changes from "real" n, (whether one lesser or one higher than needed), the difference in the mentioned logarithmic ratios is enormous (here, > 1^ -10). Its so simple, yet so powerful; I am happy to learn. :)
            double loghw = log (h) / log (w);
            while (fabs(log(n + 1)/log(n) - loghw) > 1e-10)
                n++;

The remaining part of the code is to calculate nw, non-working cats and th, total height of all cats. I use tempN and tempH as copies of n and h for the loops. Since the depth for h to reach 1 is same as 1 cat to become w:

for tempH:= h to 1
  • Reduce tempH by a factor of n+1
  • Increase tempN:= 1 by a factor of n (no. of cats will automatically reach w). 
  • Increase nw:= by tempN, the no of cats at each depth. (I remove no. of cats at the last depth from this after the loop since they are working ones, to get non-working cats)
  • Increase th, total height:= by height x no. of cats at each depth. (Since I started with value of h for th in the beginning, I knock it off in the end. Might work if start with 0 for it and not remove h off it in the end).
Simple enough, I guess.
        nw = 1;
        tempN = 1;
        tempH = h;
        th = h + w;
        for (i = 0; tempH > 1; ++i) {
            th += tempH * tempN;
            tempN = n * tempN;
            nw += tempN;
            tempH /= (n+1);
        }
        nw = nw - tempN;
        th -= h;

        cout << nw << " " << th << endl;

    }
}

Looks like all "worked hard like a dog" chasing the "cats in the hat". :)

Followers