HangOver ACM problem!

4

there is only one rule: get accept for this problem http://acm.ut.ac.ir/sc/problemset/view/1032!

to submit your code, you need to create an account(if you don't want to do so, just post your code here and I'll submit it). so far shortest code is written with C and has 85 character length.

winner will be the shortest C/C++ code submitted before 2012/02/01

note: to check shortest codes submitted you can click on "accepted runs" and then "code length"

as elssar suggested I've copied the question here :

How far can you make a stack of cards overhang a table? If you have one card, you can create a maximum overhang of half a card length. (We're assuming that the cards must be perpendicular to the table.) With two cards you can make the top card overhang the bottom one by half a card length, and the bottom one overhang the table by a third of a card length, for a total maximum overhang of 1/2 + 1/3 = 5/6 card lengths. In general you can make n cards overhang by 1/2 + 1/3 + 1/4 + ... + 1/(n + 1) card lengths, where the top card overhangs the second by 1/2, the second overhangs tha third by 1/3, the third overhangs the fourth by 1/4, etc., and the bottom card overhangs the table by 1/(n + 1). This is illustrated in the figure below.

figure http://acm.ut.ac.ir/sc/assets/problem_images/1032_50ac13c53158fd843d1884e8afa962dd.jpg

Input

The input consists of one or more test cases, followed by a line containing the number 0.00 that signals the end of the input. Each test case is a single line containing a positive floating-point number c whose value is at least 0.01 and at most 5.20; c will contain exactly three digits.

Output

For each test case, output the minimum number of cards necessary to achieve an overhang of at least c card lengths. Use the exact output format shown in the examples.

Sample Input

1.00
3.71
0.04
5.19
0.00

Sample Output

3 card(s)
61 card(s)
1 card(s)
273 card(s)

Ali1S232

Posted 2012-01-16T11:26:08.983

Reputation: 417

Would be nice if you copied the question over here. – elssar – 2012-01-16T14:30:58.370

I just saw a guy on 9gag that recently posted an image of this :) – ajax333221 – 2012-01-16T18:53:50.537

Shouldn't there be 5 outputs for 5 inputs? – Thomas Eding – 2012-01-17T04:38:51.300

1I know the problem says C/C++, but that's for the ACM site. Can we post answers in other languages here on CG? – elssar – 2012-01-17T07:24:57.497

@trinithis 0 is used to terminate input, so it's not really an input to program. In any case, the answer for 0 would be trivial - 0 – elssar – 2012-01-17T07:33:26.593

>

  • why should this not be language-agnostic? Allright, this ACM site doesn't seem to accept many languages, but it would be easy to write a test script which does. — 2. this pretends to be a physics problem, but it's readily seen that the harmonic series does not predict the correct maximum overhang: the center of mass of the uppermost two cards is in the middle of their intersection, but the next card below only reaches 1/3 into that intersection, so the uppermost cards would tip over.
  • < – ceased to turn counterclockwis – 2012-01-18T16:18:11.450

    The correct solution is actually a harmonic series, but not 1/2 + 1/3 + ... but 1/2 (1 + 1/2 + 1/3 + ...).

    – ceased to turn counterclockwis – 2012-01-18T16:38:04.100

    @leftaroundabout that really doesn't matter right now! it was actually a challenge between me and a bunch of my friends. – Ali1S232 – 2012-01-18T18:23:48.600

    Answers

    2

    C, 149 89

    Well, this was a noobish shot at it, but probably a decent starting point:

    #include <cstdio>
    float i;
    int o(float a,int n=2){return a<0?n-2:o(a-1./n,n+1);}
    main(){if (scanf("%f",&i),i==0) return 0;printf("%d card(s)\n",o(i));main();}
    

    It reported as 145 characters.


    With a push in the right direction, I got the solution down to 122 by changing the function to a for loop.

    #include <cstdio>
    float i;
    main(){
    if (scanf("%f",&i),i==0) return 0;
    int n=2;for(;i>0;)i-=1./n++;
    printf("%d card(s)\n",n-2);
    main();}
    

    On a roll!

    #include <cstdio>
    main()
    {
        float i,n=2;
        for(scanf("%f",&i);i>0;i-=1/n++);
        if (n-=2) printf("%.0f card(s)\n",n), main();
    }
    

    Scooted scanf, for loop division doesn't need 1. any more, adjusting n now done in conditional.


    Switched over to C, got some good savings. Down to 89 characters.

    main(n)
    {
        float i;
        for(scanf("%f",&i);i>0;i-=1./++n);
        if (--n) printf("%d card(s)\n",n), main(1);
    }
    

    Mr. Llama

    Posted 2012-01-16T11:26:08.983

    Reputation: 2 387

    A for( loop is probably going to be more concise than a recursive function for the calculation in o(. Maybe something like main(){if (scanf("%f",&i),i==0) return 0;for(n=2;i>0;n++)i-=1./n;printf("%d card(s)\n",n-2);main();} (if I understand your logic correctly). (Demo: http://www.ideone.com/CgFbp) Also there are some extra spaces that can be removed (ex. between if ( and ) return).

    – mellamokb – 2012-01-16T18:54:50.613

    Turns out that the way the program is judged, whitespace doesn't matter (which is actually kinda nice for readability). – Mr. Llama – 2012-01-16T19:02:37.703

    1A few more optimizations: main(){scanf("%f",&i);for(n=2;i>0;i-=1./n++);n-=2;if(n)printf("%d card(s)\n",n),main();} Edit: Just tried submitting it, was accepted as 115 characters :). I removed return statement, moved check for i==0 to be instead a check of if(n) toward the end. – mellamokb – 2012-01-16T19:03:09.980

    Got 3 more characters off: Combine definitions to float i,n=2; and change printf to use %.0f to round the float value. – mellamokb – 2012-01-16T19:14:31.617

    You can shave off just a bit more by defining and initializing n just before the for loop: int n=2;for(;i>0;i-=1./n++) – Mr. Llama – 2012-01-16T19:15:24.817

    Moved scanf into for( initialize, and use n-2 instead of n-=2 (from my last solution) and I saved 2 more, down to 110 characters currently (http://www.ideone.com/koW7Y). I have a feeling that the final optimizations will not be possible without switching to C first.

    – mellamokb – 2012-01-16T19:21:00.470

    Hmm.. I had tried if (n-=2) and got an error. Oh well, you can save one more character by moving the scanf( into the first part of the for( :) – mellamokb – 2012-01-16T19:22:56.333

    0

    As I said so far there is an answer with 85 characters written in C99 (note that white spaces are not counted)

    main(i){for(float x;i=scanf("%f",&x),x;printf("%d card(s)\n",--i))for(;x>0;x-=1./++i);}
    

    that was the whole code, hope It gives you the idea how to optimize it!

    Ali1S232

    Posted 2012-01-16T11:26:08.983

    Reputation: 417

    It seems we were on similar paths then... I'm currently 4 characters higher, but making good progress (I think). If anything, I'm glad to have come close without knowing the current best entry. – Mr. Llama – 2012-01-16T19:56:23.237

    I know two other codes (almost the same as this one) with 85 characters, but so far I couldn't find anything better than This – Ali1S232 – 2012-01-16T20:05:11.807