Code-golf techniques, part 1

Somewhat related photo by sydney Rae on Unsplash

Update: there are more things in part 2.

There is a game for programmers — code golf, and its particular implementation — code-golf.io. The goal is to write a shortest possible program to perform some task, and that can be done in a variety of programming languages.

I have spent some time playing this game, and accumulated a number of techniques that help making programs short, and I want to share these techniques.

Disclaimer:

  • I’m not particularly good at code-golf, and I’m pretty sure there are much more advanced things that make your code shorter. And I’m not claiming this is a full list or anything like that.
  • I’m not going to provide ready solutions to any tasks. Not spoiling the fun! But there will be code snippets.
  • Discovering these techniques is fun on its own, so, maybe you should stop reading.
  • I’m going to talk mostly about JavaScript.
  • Some techniques are really obvious. Unless it’s four in the morning and you’re having your 17th cup of coffee. Real story here…
  • What is written below is not a good practice, not a clean code, not an elegant solution, nothing like that. The only criteria is: it saves characters? then it’s legit. I believe only some of these things can be used outside golfing.

Literals

  • Check if you really need exact value, e.g. task could mention “in range from 1 to 1000” but actual last that satisfies given conditions value could be something like 998.
  • Another thing would be using scientific notation:
// Long:
for(i=0;i<10000;i++)
// Shorter:
for(i=0;i<1e4;i++)
  • Array of strings might be better formed by doing a split. If particular set of values allows that, use digit as delimiter to make expression shorter:
// Longest:
['here','goes','some','set','of','misc','strings']
// Shorter:
'here goes some set of misc strings'.split(' ')
// Shortest:
'here0goes0some0set0of0misc0strings'.split(0)
  • Don’t use unicode sequences as actual characters are counted as 1 symbol, not as 2 or more UTF-8 bytes:
// Unusable:
a=String.fromCodePoint(128513)
// Long:
a='\u{01F601}'
// Shortest:
a='😁'

Variables

  • Define by assigning initial value instead of let, const, var (and don’t forget they are global because of that):
// Long:
let a=1,b=2,c=3
// Short:
a=1,b=2,c=3
  • If using functions, check if you really need to pass variable; maybe having it global is just OK:
// Long:
f=(k,n)=>k<n?k+f(k-1,n):0
f(3,5)
// Short:
n=5;f=n=>k<n?k+f(k-1):0
f(3)
  • If you need variable local to function, define it as parameter, possibly with initialization:
// Example usage:
g(10,v=>g(5,print))
// Can't reuse global i, the following won't work with recursion:
g=(n,f)=>{for(i=1;i<10;i++)f(i)}
// This one is safe, and only one character longer:
g=(n,f,i=1)=>{for(;i<10;i++)f(i)}
  • Use chained assignment if initial values are the same:
// Long:
for(a=0,b=0,c=0;a<10;a++)
// Short:
for(a=b=c=0;a<10;a++)
  • If you need to initialize array with some values, and some variables need to have same initial values, combine everything:
// Long:
for(m=[0],i=0;i<10;i++)
// Short:
for(m=[i=0];i<10;i++)
  • Destructuring assignment could be very useful:
// Swapping values:
[a,b]=[b,a]
// Computing next value and storing previous, all in one move:
[p,c]=[c,c*2]
  • Also, destructuring array into single variables might be shorter than using indexes:
// Long:
X[0]+X[1]*X[2]+X[2]/X[3]
// Short:
[a,b,c,d]=X;a+b*c+c/d

That’s all for now. In the next story I’ll cover some expressions, type conversions, and more.