Code golfing is a discipline where you solve a programming task by using the fewest amount of characters possible. Depending on the chosen language this can be more or less readable when done.
Codingame, a website offering various coding challenges, has a two categories where the code-golfing principle is the winning factor: classic code-golfing challenges with no time limit, where you try to optimize your code-size forever and Clash of Code “Shortest Mode” where you have to solve a task within 15 minutes and, by default, you compete against up to 7 other players.
Codingame made a cheat-sheet-blog-post some years ago which contains a whole bunch of useful information: https://www.codingame.com/blog/code-golf-python/
Here are my notes on how to reach lower code-size using Python 3 with examples – updated whenever a new idea is found:
General ideas
Variables
If a variable is used only once, inline it. (But only start inlining once your solutions works correctly on all test-cases):*l,=input() for i in l:...
becomes (l
is used only once):for i in input():...
Initialization
When looping (to sum up or similar), initialize the variables in a way that the first (wrong) action (a comparison for example) in a loop sets them to right initial value afterwards.
Example: count differences of neighboring chars in a string, r starts with -1 and the first difference (which should not be done), makes it jump to 0. (Example from TFeld)r=p=-1 for c in input():r+=c!=p;p=c
Input handling
Basically all Codingame-challenges require to read input-data from standard input. The input data is always human-readable ASCII-characters. Lists are represented with space-separation or line-separation or both. It can be only integers or floats or strings or a mix of these.
For different presentations there are different shortest ways to read them.
One element
String: v=input(
)
Integer: v=int(input())
String, all chars into a list: *l,=input()
Non-decimal integer literal (hexadecimal, binary, octal): v=eval(input())
Multiple elements, one line, same type
split() without arguments splits spaces (
) and new-lines (
)\n
Strings, to list: l=input().split()
Integers, to list: l=map(int,input().split())
Multiple elements, multiple line, same type
Cannot use input()
any longer, it only reads one line.
Strings, to list: *l,=open(0)
Integers, to list: *l,=map(int,open(0))
Multiple elements, multiple line, different type
Often item-counts are given as a single line and the real data is starting on the following line only. Item-counts can generally be ignored in python:3
1 2 3
Item-count and integer on one, to list: _,*l=map(int,open(0).read().split())
or3
a b c
_,*l=open(0)
# still contains the \n_,*l=open(0).read().split()
# no more \n_,*l=map(str.strip,open(0))
# no more \n
or2 3
a b c
d e f
Item-count and strings on lines, to list: r,c,*l=open(0).read().split()
Output
Arrays/Generators
Printing space separated array: print(*l)
, when using short-input: I(' '.join(l))
Printing one item per line: print(*l,sep='\n')
, when using short-input: I('\n'.join(l))
Strings
String are lists when it comes to indexing and iterating.
Reverse (palindrome check): s==s[::-1]
Capitalize each word in a sentence: str.title()
or str.capitalize()
Align with stuffing: str.ljust(width, fillchar)
– same with rjust()
and center()
Algorithms
Prime numbers
Is prime number: all(x%m for m in range(2,x))
(source) (as lambda if needed several times, doesn’t work for 1)
Run length encoding
Use itertools.groupby()
: s='aaabbbccc' r=''
for a,b in itertools.groupby(s):
r+=str(len(list(b)) + a
r == '3a3b3c'
Number of type of character
Vowels: sum(word.count(i) for i in 'aeiouAEIOU')
Consonants: len(w) - sum(word.count(i) for i in 'aeiouAEIOU')
Distance of 2D-points
Use complex: px,py,ox,oy=0,0,1,1; abs(ox-px+(oy-py)*1j)
Roman numbers
Convert roman number to decimal by using a table with basic _and_ special numbers:
for x,y in zip(['IV','IX','XL','XC','CD','CM',*'IVXLCDM'],
[4,9,40,90,400,900,1,5,10,50,100,500,1000]):
c+=s.count(x)*y
s=s.replace(x,'')
Special loops
Popping pairs, triplets, etc.
If an multi-element-input is read into an array (with open(0)
for example), iterating over it pairwise or triple-wise this way:d=[1,2, 2,3, 4,5, 6,7]
while d:
x,y,*d=d
Summing items for different arrays
List of sums for each pair: l=list(map(sum,zip(a,b)))
Use members for map()-call
Max occurrence of chars in a string: max(map(s.count,s))