4

I am trying to solve the SPOJ problem "Cricket Tournament". I wrote the code in python and also in c. In python it takes about 2 seconds for input 0.0 0/0 300. But in C it runs forever. Code in C is running for some smaller test cases like 19.5 0/0 1

Code in C

#include<stdio.h>
float ans[10][120][300]={0};
float recursion(int balls, int reqRuns, int wickets);
int readScore(void);

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(ans,0,sizeof(ans));
        float overs;
        int myruns,wickets,target;
        scanf("%f",&overs);
        myruns=readScore();
        scanf("%d",&wickets);
        //printf("%d %d\n",myruns,wickets );
        scanf("%d",&target);
        //printf("%d %d %d\n",myruns,wickets,target);
        if(myruns>=target)
        {
            printf("%s\n","100.00");
            continue;
        }
        else if(wickets>=10)
        {
            printf("%s\n", "0.00");
            continue;
        }
        printf("overs = %f\n", overs);
        int ov = (int) overs;
        int ball = (int)(overs*10)%10;
        int totballs = 6*ov+ball;
        //printf("%d %d\n",ov,ball );
        //printf("%d %d %d\n",totballs, target- myruns,wickets );
        float finalAns = recursion(totballs,target-myruns, wickets)*100;
        printf("%.2f\n",finalAns);

    }
    return 0;
}

int readScore()
{
    char ch;
    int ans2=0;
    ch = getchar();
    //ch = getchar();
    //ans = ans*10 + ch-'0';
    //printf("sadasdas %d\n",ch );
    while(ch!='/')
    {
        ch=getchar();
        //printf(" ch = %d\n", ch-'0');
        if(ch!='/')
        ans2 = ans2*10 + ch-'0';

    }
    //printf("%d\n",ans );
    return ans2;
}

float recursion(int balls, int reqRuns, int wickets)
{
    if (reqRuns<=0)
        return 1;
    if (balls==120||wickets==10)
        return 0;
    if(ans[wickets][balls][reqRuns]!=0)
        return ans[wickets][balls][reqRuns];

    ans[wickets][balls][reqRuns] = (recursion(balls+1, reqRuns,wickets)+recursion(balls+1, reqRuns-1,wickets)+
    recursion(balls+1, reqRuns-2,wickets)+recursion(balls+1, reqRuns-3,wickets)+
    recursion(balls+1, reqRuns-4,wickets)+recursion(balls+1, reqRuns-5,wickets)+
    recursion(balls+1, reqRuns-6,wickets)+recursion(balls+1, reqRuns,wickets+1)+
    2*recursion(balls, reqRuns-1,wickets))/10;
    return ans[wickets][balls][reqRuns];
}

Code in Python

from __future__ import division

saved = {}
t = input()

def func(f):
    if f in saved:    return saved[f]
    x,y,z,n = f 
    if z >= n:    return 1
    if x == 120:    return 0 
    if y == 10:    return 0

    saved[f] = (func((x+1,y+1,z,n)) + func((x+1, y,z,n)) + func((x+1,y,z+1,n)) + func((x+1, y, z+2,n)) + func((x+1, y, z+3,n)) + func((x+1, y, z+4,n)) + func((x+1, y, z+5,n))+ func((x+1, y, z+6,n))+ func((x,y,z+1,n)) + func((x,y,z+1,n))) / 10
    return saved[f]

def converter(f):
    v = f.index('.')
    x,y = int(f[:v]), int(f[-1])
    return x*6+(y)

for i in range(t):
    x,y,z = raw_input().split()
    v = y.index('/')
    q = int(y[:v])
    x,y,z = converter(x), int(y[(v+1):]), int(z)
    print  '%.2f' % (100 * func((x,y,q,z)))
Ishan Jain
  • 262
  • 2
  • 14

3 Answers3

3

Your problem is that a lot of the results of the recursion are 0, so

if(ans[wickets][balls][reqRuns]!=0)
    return ans[wickets][balls][reqRuns];

fails to return the cached result in many cases, hence you're recomputing many many results, while the check f in saved in Python prevents recomputation of the same values.

I changed your C code to set the initial entries of ans to contain negative numbers (if you know the floating point representation of your platform to be IEEE754, simply changing to memset(ans, 0x80, sizeof ans); will do), and replaced the condition with

if (ans[wickets][balls][reqRuns] >= 0)

and got the result immediately:

$ time ./a.out  < spoj_inp.txt 
overs = 0.000000
18.03

real    0m0.023s
user    0m0.020s
sys     0m0.002s
Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
  • Thanks for pointing out the mistake. I corrected it and now it is running fine. **But the correct ans for this case is 18.02 not 18.03.** I am getting 18.03 even through python code. – Ishan Jain Oct 01 '12 at 22:56
  • The output specification says "Note: The first two decimal places in it's representation should be printed without rounding", `%.2f` rounds. The result is `18.027...`. – Daniel Fischer Oct 01 '12 at 23:05
  • Oh! Thats a new information for me. %.2f rounds off!! Should I convert it to string and print upto 2 decimals or is there any better way? – Ishan Jain Oct 01 '12 at 23:23
  • Solved that problem and getting correct output for test cases displayed but still getting **wrong ans** after submitting. I am frustrated now. It took my whole day but still not able to code, though it took very less time to think about the algo. Could you please review my new code and tell me if I am missing anything like an edge case or something? [My new code](http://ideone.com/Fn8Jr) – Ishan Jain Oct 01 '12 at 23:59
  • It could still be the same problem. If the exact (calculated) result is e.g. 34.03972... it would be rounded to three digits after the decimal point, giving 39.040. You could `sprintf` with more digits, ten would make it extremely unlikely that such an edge case occurs (and then you'd have to worry about floating-point error accumulation anyway). Or you can multiply by 100, `floor`, divide by 100, or subtract 0.005 (both still need `%.2f`). All these get some edge cases wrong, but if those arise, you have far bigger problems with accuracy of operations (`*`, `+`). – Daniel Fischer Oct 02 '12 at 11:05
0

The problem is with your use of scanf. It treats space or newline as terminator of an input. Mostly likely you are typing enter after each input. However, problem is that it leaves the \n in the buffer and that is passed to the next input.

If you are not using strict c, you can call

cin.ignore()

after each scanf call. I tried it on your code and was able to get successful output.

Alternately, you can call

fflush(stdin);

This might be helpful too

scanf at stackoverflow

Community
  • 1
  • 1
fkl
  • 5,412
  • 4
  • 28
  • 68
  • I am getting right ans for several other cases. So this is not an issue. To get over that issue I used getchar at the 3rd line of readscore function to read any whitespace. – Ishan Jain Oct 01 '12 at 19:16
  • Then you should copy at least one test case that fails. This was vital information for your question – fkl Oct 01 '12 at 19:19
  • And i believe as mentioned above already, this is the problem if(ans[wickets][balls][reqRuns]!=0) return ans[wickets][balls][reqRuns]; ans is a float so even if it's value is 0.0000, it will not be equal to 0. You might have a few cases which got through this but not every case. Type cast this to integer or do a comparison like this float - 0 < 0.000 to be sure – fkl Oct 01 '12 at 19:21
  • I mentioned it explicitly in my question. It is not running for 0.0 0/0 300. It runs and returns correct ans for case 19.5 0/0 1 – Ishan Jain Oct 01 '12 at 19:22
  • The way you wrote in question is: It runs in python but runs forever in c. Doesn't sound like there was a success case for c. Above is explicit – fkl Oct 01 '12 at 19:25
  • I tried typecasting it but no help. Updated Code:-if((int)ans[wickets][balls][reqRuns]!=0) – Ishan Jain Oct 01 '12 at 19:26
  • `fflush(stdin)` has *undefined behavior* (http://www.c-faq.com/stdio/stdinflush.html). I do agree to avoid using `scanf` (even if it's not the cause of the problem here); `scanf` is notoriously hard to use (http://www.c-faq.com/stdio/scanfprobs.html). – jamesdlin Oct 01 '12 at 19:44
  • Thanks for clearing that up. I always used cin.ignore(). Rather personally, i always used cin.getline() and atoi() latter for numbers etc. Just thought fflush as a pure c equivalent since in my case of this scenario, it was always c++. This is added info for me. Thanks. – fkl Oct 01 '12 at 19:56
0

I guess the recursion is to be blamed here. Code does work for smaller targets. Get rid of recursion if possible.

With smaller targets:

input

2
0.0 0/1 10
0.0 2/2 20

output

100.00
99.99
जलजनक
  • 3,072
  • 2
  • 24
  • 30
  • 1
    Since the code with same algorithm(using recursion) is running in python, in my opinion this should not be an issue. – Ishan Jain Oct 01 '12 at 19:28