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 2011-01-28T12:23:33.527

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 – 2016-04-21T16:47:20.283

@TobySpeight Probably because they have the same url besides the question ID. – NoOneIsHere – 2017-01-05T19:22:35.453

C and C++, even if not 'golfing' type, are right and easy (if one consider the right subset of C++) – RosLuP – 2019-08-12T21:37:33.280

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 2011-01-28T12:23:33.527

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 – 2012-10-04T10:09:02.187

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 – 2012-10-04T13:03:44.630

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 – 2019-12-02T02:58:48.973

Replace std::endl with '\n' that saves 5 chars – Mukul Kumar – 2014-03-24T14:01:12.093

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 – 2014-03-24T15:05:13.843

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 2011-01-28T12:23:33.527

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 2011-01-28T12:23:33.527

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 2011-01-28T12:23:33.527

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 – 2019-07-17T20:29:37.207

@celtschk yes, good point. But if you're purely doing the boolean algebra, then it works – Baldrickk – 2019-07-24T11:03:38.717

@S.S.Anne the point is you can use x*y saving a character. – Baldrickk – 2020-02-07T09:55:29.500

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 – 2014-09-11T11:15:56.023

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 – 2014-09-11T11:33:35.230

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 2011-01-28T12:23:33.527

Reputation: 256

11

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

Mechanical snail

Posted 2011-01-28T12:23:33.527

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 2011-01-28T12:23:33.527

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 – 2019-12-02T03:01:12.803

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 – 2014-04-10T19:41:10.347

7These two tips would be better placed in two separate answers so they can be voted on individually. – trichoplax – 2014-08-13T02:53:57.130

10

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

NaCl

Posted 2011-01-28T12:23:33.527

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 2011-01-28T12:23:33.527

Reputation: 2 292

How about x=1,y=2/*...*/else x++,y++? – S.S. Anne – 2020-02-06T18:08:34.613

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 2011-01-28T12:23:33.527

Reputation: 14 620

I wish I could star answers. This is good. – S.S. Anne – 2020-02-06T18:10:35.620

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 2011-01-28T12:23:33.527

Reputation: 586

7why not for(int* i=array; i<array+25*25; i++)? Then you only have to keep track of one variable. – Lucas – 2015-08-13T17:45:50.637

Don't forget you can cut out all that whitespace! (Different tip altogether, but should be mentioned) – stokastic – 2014-09-11T13:19:53.577

@stokastic The examples aren't meant to be golfed, only to demonstrate how to use the technique. – Stuntddude – 2014-09-12T02:54:54.710

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 2011-01-28T12:23:33.527

Reputation: 180

5If you only use a single name, but that quite often, using std::name; may be shorter, though. – celtschk – 2014-04-10T19:44:05.933

12This only saves characters if you use std:: five or more times. – nyuszika7h – 2014-06-12T19:00:19.137

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 2011-01-28T12:23:33.527

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 – 2017-12-08T09:47:17.917

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 2011-01-28T12:23:33.527

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 2011-01-28T12:23:33.527

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 – 2016-09-23T05:33:04.193

r?foo():0; // if (r) foo() this is ok;;;;; but For this r?:foo(); i don't Know that – RosLuP – 2018-01-28T20:22:54.123

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 2011-01-28T12:23:33.527

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 – 2019-02-14T09:34:39.937

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 – 2019-02-14T10:33:29.543

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 – 2019-02-14T10:45:01.623

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 – 2019-12-02T03:15:33.793

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 – 2019-12-02T03:22:56.687

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 – 2019-12-03T20:52:43.947

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 2011-01-28T12:23:33.527

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 2011-01-28T12:23:33.527

Reputation: 211

#import is a deprecated GCC extension. But still is supported by modern versions of GCC. – Peter Cordes – 2019-12-02T03:07:50.673

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 2011-01-28T12:23:33.527

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 2011-01-28T12:23:33.527

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 – 2016-09-28T23:58:18.277

Yes possible a+=a--; has Undefined Behaviour – RosLuP – 2018-01-28T20:28:12.817

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 2011-01-28T12:23:33.527

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 – 2019-10-02T23:58:46.643

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 2011-01-28T12:23:33.527

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 2011-01-28T12:23:33.527

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 2011-01-28T12:23:33.527

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 2011-01-28T12:23:33.527

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 2011-01-28T12:23:33.527

Reputation: 171

0

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

user54200

Posted 2011-01-28T12:23:33.527

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 – 2017-12-08T09:49:30.177