Code golfing – Python 3 notes

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())

or

3
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

or

2 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))

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.