7

I am taking part in a small programming competition online. Basically what I do is solve a task, write an algorithm and send my code to be automatically evaluated by the competition holder's server.

The server accepts a wide variety of programming languages. All the tasks basically require the program to take input from the terminal and output a correct to the terminal as well. So on the competition holder's website I noticed that one of the languages they support is C++ and they use g++ to compile it. Well, since I'm not that fluent in C++ as opposed to C I thought I would return my answers in C.

This worked great for the first task. However in the second task I constantly hit the limit set for the execution time of the program (2 seconds)

This is my C code:

#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <stdlib.h>

uint8_t get_bit(uint64_t k) {
    ...
}

int main(int argc, char *argv[]) {
    uint64_t n;
    uint64_t k;
    scanf("%u", &n);

    uint64_t i;
    for (i = 0; i < n; i++) {
        scanf("%u", &k);
        printf("%d\n", get_bit(k));
    }

    return 0;
}

So my algorithm is defined in get_bit. The server runs 3 different tests on my program, with different values, mostly increasing to make the program run longer.

However, this code in C failed the tests due to taking more than 2 seconds to run. Trying different solutions for hours with no avail, I finally tried to submit my code as C++ with a little different printing methods.

Here is my C++ main (the rest of the program stayed mostly the same):

int main(int argc, char *argv[]) {
    uint64_t n;
    uint64_t k;
    cin >> n;

    uint64_t i;
    for (i = 0; i < n; i++) {
        cin >> k;
        cout.operator<<(get_bit(k)) << endl;
    }

    return 0;
}

And when I submitted this code, all the tests ran perfectly in just a few hundred milliseconds each. Note that I did not alter my algorithm in get_bit but only the printing.

Why is printing in C++ so much faster than in C? (in my case up to 10x faster) If it's possible, how can I achieve these speeds in C as well? As you might probably notice, I am not fluent in C++ and the previous code is mainly copy paste. For this reason I would much rather prefer to program in C.

Thank you in advance.

vuolen
  • 464
  • 4
  • 12
  • How big is the input? – Keith Thompson Oct 06 '16 at 20:00
  • 2
    `scanf("%u", &n);` likely isn't completely initializing `n`, so the for loop runs a different number of times possibly. Did you try running the programs locally to see if you got differing behavior - like many more lines of output in the C program run? – Michael Burr Oct 06 '16 at 20:04
  • Your compiler should give you warnings about using `"%u"` with a `uint64_t`. Turn on warning flags! – DeiDei Oct 06 '16 at 20:05
  • No need to guess. Just do [*this*](http://stackoverflow.com/a/378024/23771) on the slow program and it will immediately show you why. – Mike Dunlavey Oct 06 '16 at 20:05
  • 1
    One idea of these challenges is that you use a naive solution to prove your code for the test cases, and to get a feel for the question, but it won't be fast enough for the real job. So that's the actual task, and IMO it is bad form to ask others how to solve these programming challenges. And that is why I went against the stream and downvoted the question. – Weather Vane Oct 06 '16 at 20:07
  • @KeithThompson n is between 1 and 10^5, k is between 1 and 10^18 – vuolen Oct 06 '16 at 20:18
  • And here I thought you might have voted against the question because its premise is outlandish, @WeatherVane. – John Bollinger Oct 06 '16 at 20:18
  • @WeatherVane You have a good point. Personally I justified asking this because 1) I have already completed the assignment and 2) I feel the point of these assignments are to test my ability to solve problems using algorithms, not really to know everything about the language or to know how to print fast. – vuolen Oct 06 '16 at 20:21
  • 1
    @JohnBollinger sorry I don't get you. I prefer to make upvotes than downvotes. – Weather Vane Oct 06 '16 at 20:26
  • Just curious, have you tried `cout << get_bit(k) << '\n';` too? – Bob__ Oct 06 '16 at 20:30
  • @WeatherVane, you having already disclosed that you DV'd the question, I was snarkily remarking on the absurdity of its apparent premise that printing from C++ is substantially faster than printing from C. I don't doubt that one *program* runs much faster than the other, but that's an altogether different matter. – John Bollinger Oct 06 '16 at 20:30
  • 1
    @JohnBollinger I get you now. It's not the challenge itself that is absurd, but may I add, was not the one who gave the accepted answer a DV. – Weather Vane Oct 06 '16 at 20:35

1 Answers1

6

It is probably because your code is may be (see comments) incorrect. You cant use %u with scanf and 64-bit integer.

Check the third table here http://www.cplusplus.com/reference/cstdio/scanf/ . You should use sth like %llu.

ciechowoj
  • 914
  • 6
  • 26
  • 1
    Well, you can if `unsigned int` is 64 bits, but it probably isn't. – Keith Thompson Oct 06 '16 at 20:02
  • 4
    It's possible that this causes the lower part of `n` to be set by `scanf()` while leaving the upper part at some (seemingly) random value, causing far, far too many loop iterations (or vice versa). – Dmitri Oct 06 '16 at 20:05
  • 3
    The correct header is `` and the macro should be `SCNu64` for `scanf()` (and would be `PRIu64` for `printf()` if printing `uint64_t`, which the code isn't). So if should be `scanf("%" SCNu64, &k);` to be correctly safe on all platforms (that support Standard C ``). – Jonathan Leffler Oct 06 '16 at 20:07
  • @JonathanLeffler: You could also use `"%llu"` to scan into an `unsigned long long` and then copy the value to the `uint64_t` variable. (I mention that because I find the macro names in `` a bit unwieldy, and the alternative can be used with any integer type, not just the ones supported by ``.) – Keith Thompson Oct 06 '16 at 20:25
  • I think you were right before you corrected yourself. Unless there is a good engineering reason for a specific piece of code to not be portable, not being portable makes the code incorrect by default as far as I am concerned. Before there were standard headers for this it was already common practice to isolate stuff like this in a "platform.h" and define them there. Now that there are standard headers, there is literally no excuse for this kind of thing. – Tim Seguine Oct 06 '16 at 20:42