Tips for golfing in C++

51

21

What general tips do you have for golfing in C++?

I'm looking for ideas that can be applied to code golf problems in general that are at least somewhat specific to C++ (e.g. "remove comments" is not an answer). Please post one tip per answer.

(Tips that apply to C as well can be found in Tips for golfing in C - but note that some C tips don't work in C++. For example, C++ does require function prototypes and return values.)

marcog

Posted 15 years ago

Reputation: 10 244

4

Many of the tips for golfing in C are also applicable to C++, so please assume that readers are familiar with that question; only post here if you have something that isn't also a valid C golfing tip.

– Toby Speight – 10 years ago

@TobySpeight Probably because they have the same url besides the question ID. – NoOneIsHere – 9 years ago

C and C++, even if not 'golfing' type, are right and easy (if one consider the right subset of C++) – RosLuP – 6 years ago

Answers

26

The ternary conditional operator ?: can often be used as a stand in for simple if--else statements at considerable savings.

It is of special value in that it can be used to select alternate lvalues as in

#include <iostream>
#include <cstdlib>
int main(int c, char**v){
  int o=0,e=0,u;
  while(--c) ((u=atoi(v[c]))%2?o:e)+=u;
  std::cout << "Sum of odds " << o <<std::endl
            << "Sum of evens " << e <<std::endl;
}

dmckee --- ex-moderator kitten

Posted 15 years ago

Reputation: 2 726

haven't run the code yet, but I don't think it works the way you say. ((u=atoi(v[c]))%2?o:e)+=u does nothing but to add the value u to the expression on the left which gets the value o or e, but the variables o and e remain unchanged so they will always be 0. check the code to see what hapens. you should use adresses to make it work – Bogdan Alexandru – 13 years ago

5@BogdanAlexandru Er...do run it. It really does work. The value of the parenthetical expression is a reference to one or the other of e and o. Note that this is different from how this operator works in c where this trick does not work because it can not be an lvalue. – dmckee --- ex-moderator kitten – 13 years ago

2But std::endl isn't "ungolfed", it's just bad style / gratuitous flushing of cout even when that's not needed. endl is the same as << '\n' plus a flush; it's a different layer of stdio that handles conversion from \n to the native platform line ending (e.g. CRLF on DOS) for text streams. If you were golfing or optimizing, you'd put the first \n into the 2nd string literal: "\nSum of evens " – Peter Cordes – 6 years ago

Replace std::endl with '\n' that saves 5 chars – Mukul Kumar – 12 years ago

4@MukulKumar Well, yes. But for the purposes of demonstrating this tip I left everything except the ternary-conditional un-golfed for clarity. – dmckee --- ex-moderator kitten – 12 years ago

25

Sometimes you can save two characters by using the fact that static storage duration variables (that especially includes all global scope variables) are automatically zero-initialized at the beginning (unlike automatic variables where you have no such guarantee). So instead of

int main()
{
  int a=0;
  // ...
}

you can write

int a;
int main()
{
  // ...
}

celtschk

Posted 15 years ago

Reputation: 4 650

17

Some compilers (e.g. GCC) support multi-character constants. This can save a few characters when a large integer value is required. Example:

int n='  ';

The value is implementation-specific. Usually the value of 'ab' is 256*'a'+'b' or 'a'+256*'b'. You can specify up to 4 characters between the quotation marks.

marcog

Posted 15 years ago

Reputation: 10 244

15

One that I found handy:

Taking advantage of the fact that non-zero values evaluate to true in boolean expressions, and that x&&y evaluates to x*y when dealing with booleans

(x!=0 && y!=0)

evaluates to

(x*y)

You just have to be aware of overflows, as pointed out below.

Baldrickk

Posted 15 years ago

Reputation: 311

2Note however that && has a short-circuit behaviour which * lacks. For example, you can't replace i++!=0&&j++!=0 with i++*j++. – celtschk – 6 years ago

@celtschk yes, good point. But if you're purely doing the boolean algebra, then it works – Baldrickk – 6 years ago

@S.S.Anne the point is you can use x*y saving a character. – Baldrickk – 6 years ago

3Technically, it's x!=0 && y!=0. But when using multiplication you need to be careful with overflows. When using 32-bit integers x = y = 65536 (and several other combinations of powers of two) would also yield x*y = 0. – Martin Ender – 11 years ago

Yes, that's right. I used it as a twodimensional array bounds check here: http://codegolf.stackexchange.com/a/37571/31477 where that didn't matter. I'll edit those points in.

– Baldrickk – 11 years ago

11

When possible, change && and || to & and | respectively.

When using simple if statements:

if(<condition>)<stuff>;

can be changed to:

<condition>?<stuff>:<any single letter variable>;

which saves a character.

Alex Gittemeier

Posted 15 years ago

Reputation: 256

11

If you're willing to use C++0x, you can use new features like lambdas.

Mechanical snail

Posted 15 years ago

Reputation: 2 213

10

Use the following types:

u64, s64, u32, s32 (or int)

For repetitive words/types, use #defines:

#define a while

It's only worth it if you use while a lot to make up for the extra 10 characters. (About 4.)

Mateen Ulhaq

Posted 15 years ago

Reputation: 1 889

What implementations provide these type names? Is there a header you need to include? u8 is probably useful as a 2-byte type name when you don't need large values. – Peter Cordes – 6 years ago

2The types u64, s64, u32 and s32 are not part of C++. They may be a non-standard extension of your compiler (I've never ever seen them, though). – celtschk – 12 years ago

7These two tips would be better placed in two separate answers so they can be voted on individually. – trichoplax – 11 years ago

10

Instead of using while(1), use for(;;), saving one character :)

NaCl

Posted 15 years ago

Reputation: 528

9

Using the comma operator in lieu of open and close braces can save a few characters, if you have a situation where your clauses have more than one statement in them:

if(c){x=1;cout<<"Hi";y=2;}else{x=2;cout<<"Bye";y=3;}

vs.

if(c)x=1,cout<<"Hi",y=2;else x=2,cout<<"Bye",y=3;###

Two characters saved on a plain IF, or three total for an IF/ELSE.

As a point of distinction between C and C++, the result of a comma expression in C++ as a whole may be used as an lvalue...FWIW.

HostileFork says dont trust SE

Posted 15 years ago

Reputation: 2 292

How about x=1,y=2/*...*/else x++,y++? – S.S. Anne – 6 years ago

8

Shorter header

This is GCC specific, it may be extensible to other compilers.

Precompiled header.

In G++ bits/stdc++.h is the precompiled header consists of all other headers. If you need to import 2 different ones you can just use this.

Shorter header.

This is all headers listed on http://en.cppreference.com/w/cpp/header:

$("#a").text(pako.inflate(atob('eJx9VkuW1DAM3HON2cOGx4o3V8lzK0q3wZ9gy90TTo+dDKCyM710yT9VqWS/2ECuzPzdhO3108vfUeCHGmUWNfJmVSMbsxo5m/VUEutZjaWsTo9NSkYfO/OvouNZDP1U4xqFOHkjNzVORmzU8YXDXcf5ym86lSIwvljBXOmWYtA7evYxbXCEi0aAAl930TM4JdiDSLYV0njQzSQNlA7Ikmy4KuDOJDFB6mGOHoVZHrPeNMsM7LhIBuWQ6C1pvW6Jjd5jKVKSXtII/qwlaIoA0EoAgHYPZy+A2GswDhCWH37tVpmkKShinZWtmzPzomkyyZoAika/GkiBRsUaU7jK5MxJULNexUGkdpaDAgvFcwKKq2Eqx1q4OCDLgOQBsdGbYIGxQV+KM9NdnmvRsgK99vIFZC95QPbSAmSvYEAeA0Jy7QxMNsdvX789RdoFbVh0Jce1+r6roHoYRXC/Fa4NAlxzN67vQXbk/xAfrn7UDEI73UjLXsUI7aXek1cru4dqIQ8Uh4H1Kl4HtRrseB8kpbEyDylg1sH84N1LjG6QY4bNqN604dpU/Ea8y4QJHLAm211jsnLzsJapDGvTaIsduBTdAt5TxTTOsCaDq+rg/Vq2WPwl0FBteQs02tY6zlsWBp++MzNUQDsaG2edNkky2JsOgae7xRe6brA3b9x2P3yqBoaiX2J6mDRP3WOdq2N4nvo3sYSYZm4RfBr/4/ghOF7IKXGOJRFD6lZszfM3p+FsimvdybhmIrQov621ZXoOYtwX/KVACG8BIbw4hPoPSwyzbepO+8txgfYJC/uvCgT7fwgGu08IBPsfEgSH3whEh7cZ6ek/LshQ/3RBdPhsQHR80yA8PtMQPmndqPhpO9Bpn7msI+bEsSfp96ZCYU7diOec+wpPOrckMvaBsz6Y9KS6//Xcp3f62LHdZu9NeFqjs7S9/gHXxXg4'), {to: 'string'}));
<script src="https://cdn.rawgit.com/nodeca/pako/master/dist/pako.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre id="a">
  
</pre>

sorted in increasing order of length.

Some of them are already longer than bits/stdc++.h, and some of them requires C++17 support. Some others are not supported by TIO G++ (for reasons I don't know of). Filter out them we have:

$("#a").text(pako.inflate(atob('eJx9VcuS3CAMvOc39p5Tak+p/MoUI2SbhIcDYrz++4BdW6WG1B7VYI36IebNRfLV8s/Ix69vb59VYVFVMLuqXCqq8q7oqyQusKql7l7XJmdzqtry36rPixj6o+p2CucUjGyqzkZc0ucLx5c+55U/NJUqUD+dIFfacoq6Y+CQ8gk/4ZMRkCC0LvoG5ww9iOTcgcZBm8kaqANQJLu4KuDFJCkD9WhTQGOWw+qmRSyo4xMZtENScKT92jIb3WOpUrP+pAv8XVvQHQGgRwCAPod3T0DcGo0HhOV32IevTNYSVHHeyTncsbxoZHajqxDBY1MKZ0E/RocmAyiFlmUdnlgDZ5CvLUPTT5uSJmSZkDIhLgUTHagxeUfJMr3ka507K/DiiiYgV5wBuWIDyJVOQI4JIVmH5SRX0vuP9y+RPqCLi06pE25rDVl/GT++HG5W9rYVhrrTgNAlJBK+sofQFdBRlpbHEWrxm8SLk57NlgHq6RoUncyiOXO3yHDr1nTauGdKfhLaQjNqk3Zcrwt/EO/tUY1I4Ia12H5N2ckWkNUc7gt4VljSmxaO/D+sS+6bEzhLZ4YRrpH6yPCifHKbPOwN8cFq1x6SDb4b5SzC4dEWBqK4pHyYbB/DH19p68D2cf+//APa+54V'), {to: 'string'}));
<script src="https://cdn.rawgit.com/nodeca/pako/master/dist/pako.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre id="a">
  
</pre>

It may happens that some of them can be replaced by shorter ones. Just binary search whether the one you need can be replaced. In particular:

cstdio -> ios        (-3 bytes)
algorithm -> regex   (-4 bytes)
vector -> queue      (-1 byte)
string -> map        (-3 bytes)
bitset -> regex      (-1 byte)
numeric -> random    (-1 byte)

user202729

Posted 15 years ago

Reputation: 14 620

I wish I could star answers. This is good. – S.S. Anne – 6 years ago

8

Since array elements are stored directly after one another in memory, instead of something like this:

for(int x = 0; x < 25; x++) {
    for(int y = 0; y < 25; y++)
        array[x][y] = whatever;
}

You can do something like this:

int* pointer = array;
for(int i = 0; i < 25*25; i++, pointer++)
    *pointer = whatever;

Obviously neither of the above are golfed, for readability, but explicitly using pointers can save you a lot of space.

Stuntddude

Posted 15 years ago

Reputation: 586

7why not for(int* i=array; i<array+25*25; i++)? Then you only have to keep track of one variable. – Lucas – 10 years ago

Don't forget you can cut out all that whitespace! (Different tip altogether, but should be mentioned) – stokastic – 11 years ago

@stokastic The examples aren't meant to be golfed, only to demonstrate how to use the technique. – Stuntddude – 11 years ago

8

Quite an obvious one, but it you are using a lot of the standard library, using namespace std; might save a few characters.

developerbmw

Posted 15 years ago

Reputation: 180

5If you only use a single name, but that quite often, using std::name; may be shorter, though. – celtschk – 12 years ago

12This only saves characters if you use std:: five or more times. – nyuszika7h – 11 years ago

7

Instead of writing big powers of 10, use e notation. For example, a=1000000000 is longer than a=1e9. This can be extended to other numbers like a=1e9+24 is better than a=1000000024.

Pranjal Jain

Posted 15 years ago

Reputation: 71

1Note that this is not exactly equivalent, need to cast to integer types before using. For example 1e9/x is not the same as 1000000000/x or int(1e9)/x. – user202729 – 8 years ago

6

It is useful to remember is that a[i] is the same as *(a+i).

Replace a[0] with *a for two character savings. Also, a[i][0] is equivalent to *a[i] and a[0][i] shrinks down to i[*a]. So if you are hard-coding a 0 index in your array, a better way probably exists.

MegaTom

Posted 15 years ago

Reputation: 3 787

6

You may use the ternary operator ?: without any expressions in the true-block (it saves a byte)

#include <iostream>

int foo()
{
    std::cout << "Foo\n";
}

int main()
{
    1?foo():0;  // if (true) foo()
    0?:foo();   // if (!false) foo()
}

Check it here

x1Mike7x

Posted 15 years ago

Reputation: 211

5

This appears to be a GNU extension and not in the C++ standard. https://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Conditionals.html#Conditionals

– ceilingcat – 9 years ago

r?foo():0; // if (r) foo() this is ok;;;;; but For this r?:foo(); i don't Know that – RosLuP – 8 years ago

5

If you want to swap two integer variables a and b then ,

a^=b^=a^=b;

can be used , saving 5 characters than the standard way

a+=b;
b=a-b;
a-=b;

joker007

Posted 15 years ago

Reputation: 151

2

About that standard way. ,t at the ints created earlier and then t=a;a=b;b=t; would have already been 3 bytes shorter than the a+=b;b=a-b;a-=b;. Still, your a^=b^=a^=b; is even shorter than that, so +1 from me. I don't know C++, but it indeed works. As a Java code-golfer I'm sad it doesn't seem to work there. :(

– Kevin Cruijssen – 7 years ago

1@KevinCruijssen Yeah , I should have mentioned C++ , I dont know java much , but a^=b;b^=a;a^=b; is working fine in java . – joker007 – 7 years ago

1No need to explicitly mention C++. All these tips are for C++. :) As a Java developer I was just curious if something similar could be done in Java, but apparently not. a^=b;b^=a;a^=b; indeed works, but is longer than the ,t+t=a;a=b;b=t;. Sorry about mentioning Java, since it's off-topic here. But nice tip for C++ codegolfers! – Kevin Cruijssen – 7 years ago

If you already have a using namespace std, (std::) swap(a,b) is shorter. To avoid #include <algorithm> or <utility>, another answer suggests GCC #import<bits/stdc++.h> to get every C++ header.

– Peter Cordes – 6 years ago

I don't know why anyone would think +- swaps are the "standard" way, though. You'd never do that outside of code golf, you'd use auto t=a; or something. XOR-swap is the better known no-temporary swap, using just 3 separate ^= statements instead of a b=a-b; that has to name b twice. But yes, you save 4 bytes vs. a^=b;b^=a;a^=b;. I guess you might consider that "standard" in a code-golf context if you don't have any spare variables you can use as a temporary. – Peter Cordes – 6 years ago

Well even if it is not the standard way, it is what I am learning in school. But yours doesn't have any overflow problems. Will there be type issues? – Varad Mahashabde – 6 years ago

5

Use GCC builtins instead of importing

If you are using a GCC compiler, it sometimes helps to use their builtin functions, such as __builtin_puts or __builtin_clz. For example,

44 bytes:

int main(){__builtin_puts("Hello, world!");}`

50 bytes:

#import<cstdio>
int main(){puts("Hello, world!");}

dingledooper

Posted 15 years ago

Reputation: 421

5

#import instead of #include gives you one more byte.

Also, the space character between #import and header is not necessarily:

#include <map>
// vs
#import<map>

And if you need something from stdlib header, you may import any header with STL container (preferable set or map) instead of cstdlib.

x1Mike7x

Posted 15 years ago

Reputation: 211

#import is a deprecated GCC extension. But still is supported by modern versions of GCC. – Peter Cordes – 6 years ago

4

Use generic lambdas as cheap templates

For types other than int, using them as function arguments can be expensive. However, generic lambdas were introduced (in C++14?) and allow any lambda to be a template - using auto for the argument types can save bytes. Compare:

double f(double x, double y)
[](auto x, auto y)

Generic lambdas are also very convenient for accepting iterators - probably the best way to accept array inputs in C++ is [](auto a, auto z), where a and z are passed as begin() and end() of the array/vector/list/etc.

Toby Speight

Posted 15 years ago

Reputation: 5 058

4

Arithmetic operations on Booleans:

Although

a*=b>0?.5:-.5

is better than

if(b>0)a*=.5;else a*=-.5;

it is not as good as

a*=(b>0)-.5

Also, using #define on anything that is used a lot. It is often shorter than using functions, since type names are not necessary.

Combine things as much as possible:

a+=a--;

is the same as

a=2*a-1;

Lucas

Posted 15 years ago

Reputation: 665

While your examples are correct, be careful of invoking undefined behavior when using x as an lvalue and x++ as an rvalue. undefined behavior and sequence points

– ceilingcat – 9 years ago

Yes possible a+=a--; has Undefined Behaviour – RosLuP – 8 years ago

3

Kind of late to the party I guess...

If you want to turn an expression into -1 and 1 instead of 0 and 1, instead of this:

int x;
if (a * 10 > 5)
    x = 1;
else
    x = -1;

do this:

int x = (a * 10 > 5) * 2 - 1;

It can save some bytes depending on usage.

Yuval Meshorer

Posted 15 years ago

Reputation: 33

1Instead of int x=(a*10>5)*2-1;, couldn't you do int x=a*10>5?1:-1;, which is 1 byte shorter? – girobuz – 6 years ago

2

If you're doing C++11 or newer (which should always be the case now), use auto for complex types, if possible.

Example: 54 Bytes instead of 66

#include<vector>
std::vector<int> f(std::vector<int> l){return l;}
#include<vector>
auto f(std::vector<int> l){return l;}

Also, as performance does not matter, for some challenges a std::list may just do the job for a few bytes less:

#include<list>
auto f(std::list<int> l){return l;}

movatica

Posted 15 years ago

Reputation: 635

2

In my first attempt at code golf for task "Subtract the next numbers" I have started from function (58 bytes)

int f(int N, int P){int F;for(F=N;P;F-=++N,P--);return F;}

then safe 5 bytes with shifting to lambda and moving initialization out of for (53)

[](int N,int P){int F=N;for(;P;F-=++N,P--);return F;}

and finally after switching from for to while I got 51 bytes:

[](int N,int P){int F=N;while(P--)F-=++N;return F;}

The ungolfed test code is something like:

#include <iostream>
int main(void)
{
    int N, P;
    std::cin >> N >> P;
    auto f = [](int N,int P)
    {
        int F = N;
        while (P--)
            F -= ++N;
        return F;
    };
    std::cout << f(N, P) << std::endl;
    return 0;
}

UPDATE:

Actually for can reach the same length as while:

[](int N,int P){int F=N;for(;P--;F-=++N);return F;}

VolAnd

Posted 15 years ago

Reputation: 296

1

Functions in <algorithm> often requires passing a.begin(),a.end() which is really long, instead you can use &a[0],&*end(a) to save 3 bytes if a is vector or string.

sort(a.begin(),a.end());
sort(begin(a),end(a));
sort(&a[0],&*end(a));

JayXon

Posted 15 years ago

Reputation: 159

0

When writing a full program you can use argc to initialize an integer variable to 1:

main(a){

is the same as:

main(){int a=1;

G B

Posted 15 years ago

Reputation: 11 099

0

G++ allows for variable-sized arrays, so there is no need to go through the lengthy pointer-malloc-new stuff.

int* array = new int[array_size];

becomes

int array[array_size];

Saves 9 bytes minimum with int.

Varad Mahashabde

Posted 15 years ago

Reputation: 171

0

Don't use string(""), use "". It saves 8 bytes.

user54200

Posted 15 years ago

Reputation:

1It's not exactly equivalent. For example "" + 'a' is char* + char, which is pointer addition, while std::string("") + 'a' is std::string + char - string concatenation. string() would work. – user202729 – 8 years ago