Tips and Tricks for Code Golfing in C++


#1

Hi there, I decided to post a topic to help people on code golfing in C++, that is, to help them get less and less characters in puzzle like Thor code size or Clones code size.

I'll list all trick that is relevant for C++ code golfing, you can help improve this topic by contributing.
I will not speak about the following common tricks:

  • All tricks relevant to code golfing in general (removing spacing, small variables names etc...)
  • All tricks that do not have to do with C++
  • All tricks relevant only for one game in particular
  • All tricks to abuse a game (almost same rule as above)

That said, here are my tricks, thanks to a lot of people:

  • Tests like if (y == 1) and if (y == 0) can be replaced by if (y) and if (!y) because y if evaluated to true is it egal to 1 and !y is egal to true if y is egal to zero.
  • Storing a letter like x="W" can be made shorter using the ascii number x=87
  • Some stuffs like std::string can be used without #include < string > if it is in another include like #include < iostream >
  • The main function can be shortened from int main() to main()
  • You can remove the braces from long if or while if it only contain expressions (not variable declaration) by changing every ';' expect the last by ','. if (!y) {c = 2; v = 3; x = 4;} become if (!y) c=2,v=3,x=4;
  • If you have an if... else situation, change it to the ternary equivalent.
    if(!y)c=v;else c=f; become c=!y?v:f;
  • and you can even use that to change if(x==0)c=4;else if (x==1)c=2;else c=3 into c=!x?4:x<2?2:3;
  • Sometimes you can gain char by inverting the condition c=!y?v:f; can become c=y?f:v;
  • Sometimes, you can use the result of an expression as 0 or 1 (equivalent to true and false) to do some trick: y=h>x?1:0 can turn into y=h>x
  • for is better than while, see @NewboO post below

WORK IN PROGRESS wink IF SOMEONE WANTS TO CONTRIBUTE, FEEL FREE TO HELP

Feel free to do the same kind of topic for other languages


Temperature Code Golf puzzle discussion
Tips and tricks for codegolfing in javascript
#3

Also ,if possible, declaring all variables of same type at the same moment.
Instead of checking all chars in a string , check only for the first character ( if those are different of course)

All that i can think of has already been said ^^

One thing i don't know enough to reduce it is getting inputs , is there a faster way than cin << var << var2 << var3; ?


#4

Why doing c=!y?v:f when you can actually do c=y?f:v?

Also, another useful trick which also works in some other languages: a for loop is almost always shorter than a while loop. Just the basic while(1) is actually longer than for(;;) and as you can put a lot of thing in the for parenthesis (even the whole body by separating every expression with ,) you generally don't need brackets which makes it even better.


#5

I think you mean cin >> var >> var2 >> var3;, you can sometimes change it to gets() or scanf() to not include iostream. This is especially true in pure C where using scanf doesn't require to #include <stdio>

Trying to being picky stuck_out_tongue I was just translating ungolfed code into golfed code, but yeah, you're right, so I add reversing a condition in tricks, thanks smile

I also forgot about the 'for vs while' thanks!


#7

This is an exemple for the @NewboO explanations:

for(;;)
{
    int i;
    cin >> i;
    i += 5;
    cerr << i << endl;
}

can be replace by:

for(int i; cin >> i; cerr << i << endl) i += 5;

There is no error x)
A for loop, that's it :

The initialization is done before the loop, so you can put what you want and you save a ";" .
Next, the condition is tested at the beginning of each turn. If you put something other than a test, the test will be considered true. You can still save a ";".
And the increase is done at the ending of each turn. Again, you can put what you want and it's another ";" saved up.
You can put several actions in each of these parts , just separate them with a comma.
So, if you have only one action in the loop , the brackets are no longer needed !

I also offer these solutions to optimize the size of your program:

  • tab[0] can be replaced with *tab .
  • In some cases, the && and || can be replace by & and | .
  • In some cases, test the first character of a string is sufficient. For exemple:

    string test;
    cin >> test;
    if(test=="blabla")
    [...]

become:

char test[9];
cin >> test;
if(test=='b')
    [...]

Good luck smile


#8

Another thing than can be done specifically for the Codingame problems is variable recycling.

If you have input which you need to get, but don't use, well then that's a variable you've created and that you don't need to reuse. Saves you declaring another variable.

Example :
int n,l; // l is unused
cin>>n>>l;

int k;
cin>>k;

Well, why not use l instead of k ? It saves space (as well as not including cin.ignore() which can be dispensed with in a fair amount of the problems).

EDIT : Forgot to mention. if one of these variables is set to 0, you can probably use it in a for loop.
Example :
for(int k=0;k!=z;k++) becomes for(;l!=z;l++).

Note : I put != instead of < because I was getting post display problems.


#9

Oups, I forgot this tip:
With ternary operator (?:), you can put several actions separated by a comma (as the for loop).
For exemple, if you want increment a variable and return a string, put the increment before the char :

cout << a?i++,"a":i--,"b" << endl;

As @CvxFous says in his first post, you can't put a variable declaration here...


#10

I think you didn't invert v and f on the second part


#11

yes thanks, fixed


#12

Sometimes abs(x) can be changed to x*x, when you don't really need the value it self, but to use it on a comparison.


#13

To replace a simple if (no else), you can use a && :

if(a>b) printf("Hello world!");
a>b ? printf("Hello world!"):0; // -1 char
a>b && printf("Hello world!"); // -2 chars


#14

Not quite. Should be "because if y evaluates to true, it is not equal to 0". In other words, y = 2 also evaluates to true.


#15

Long post, but ty @lmat for bumping this.

  1. Ternary Operator on Variables

    Another neat lil' trick with the ternary operator (wonder how many of you know this...)

    (someCondition ? var1 : var2 ) ++;
    (someCondition ? string1 : string2 ) += "ABC";

    Neat, huh? Easy switching of variables between assignments.

    a?x+="ABC":y+="ABC";  // 20 chars
    (a?x:y)+="ABC";       // 15 chars

    Not only do these work with operator+, operator+=, etc, but they also work with member functions. For example, this also works as well:

    vector<int> vec1, vec2;
    (someCondition ? vec1 : vec2).push_back(someVar);

    These couple of tricks, I think, could come in pretty handy in Power of Thor or the Clones code golfs since you're managing a lot of variables (relatively).

    Also, a warning on the ternary operator: if you're doing a CG puzzle or one that requires intensive iterations and optimisation, resort to if/else.
    For example (talking about puzzles here and not golfing now), refrain from using b = a < b ? a : b and use if (a < b) b = a;. Why? Because the assignment is costly. Every picosecond matters.

    Alright, back to golfing.

  2. Using #include <bits/stdc++.h>

    Also, it doesn't seem like anyone has mentioned #include <bits/stdc++.h> ? This header includes every header you possibly need (<algorithm>, <bitset>, <iostream>, <map>, <vector>, etc).

    Also, we don't need that space between include and <filename>. So your first 2 - 10 lines of code? You can shrink it to #include<bits/stdc++.h>.

  3. Using #define

    If you're using a function a lot (e.g. toupper, isupper, abs, push_back, etc) you can replace all the occurrences with a self-defined #define at the top. For example:

    /* headers, using std, etc etc */
    int main()
    {
        if(isupper(a) && isupper(b) && isupper(c) && isupper(d))
        {
            /* code */
        }
        return 0;
    }

    could be rewritten as

    /* headers, using std, etc etc */
    #define U isupper     // 18 additional chars including newline char
    int main()
    {
        if(U(a) && U(b) && U(c) && U(d))
        {
            /* code */
        }
        return 0;
    }

    And that would effectively minimise your code. From 28 chars (4 isupper's each 7 chars, 4 * 7 = 28) to 22 (18 from #define + 4 U's)
    How does it work? #define stores the symbol isupper into the macro U and when the code compiles, all occurrences of U are replaced with isupper.

    Lots of things you can simplify with #define but I'll leave that for you to explore on your own. :slight_smile:

    Try to be sensible about it as well. If you're trying to use #define U isupper when there's only one occurrence of isupper, then's it's better to leave it since adding a #define will incur more characters and give a negative profit of characters.

  4. Initialisation of Numbers

    You've probably experienced declaring an int inside the main function and initialising it to 0 (e.g. int a = 0;). And then we use that to count or keep track of stuff. However...

    If you need to initialise an int, long, float, etc to 0 and your priority is code size, then you should declare the variables outside the main function.

    So instead of

    #include <iostream>
    using namespace std;
    int main()
    {
        int a = 0, b = 0;
        cout << a << " " << b << endl;
        return 0;
    }

    you could do

    #include <iostream>
    using namespace std;
    int a, b;
    int main()
    {
        cout << a << " " << b << endl;
        return 0;
    }

    and your initialisation is guaranteed to be initialised to 0. Of course, this creates global variables, bad practice in the office. :wink: But hey, on the plus side you're taking away at least 2 chars from each variable initialised.

  5. Removing using namespace std

    Maybe you're doing a clash of code and you're only using cin and cout once or twice? You can try code golfing by removing using namespace std; (20 chars) and putting std:: (5 chars) in the appropriate places.

    When is this appropriate to do? Each time you use an function under the std namespace, you incur 5 chars. So if you have less than 4 calls to functions/objects in the std namespace, then you will gain at least 5 chars.
    Similar with using #define, one also needs to be sensible about removing using namespace std; as well (e.g. if you're using 2 cin's, 3 cout's, 1 pow and 2 max's, it wouldn't be sensible to remove using namespace std.

    If you're using endl (4 chars), you can replace this with '\n' or "\n" (both also 4 chars). The nice tradeoff is that you wouldn't need std:: in front endl (i.e. if you decided to remove using namespace std).


That's it for now, I think. There's probably tons more, but not recollecting any immediate ones. :confused:

Hope you learned something from all this. And remember that there is a time to golf and a time not to golf. :slight_smile: