A collection of tricks to help you code golfing with Python or to confuse your code reviewers.
I use these python tricks all the time when clashing in shortest mode on codingame or playing code golf. These are very useful. If you want to add another snippet, create a pull request. Also, it would be very nice to help sorting that unsorted stuff or just correcting english grammar (mine is not so good, I'm not a native speaker).
Also, it's highly inspired by https://tinier.js.org/. I did not find any type of collection out there for python so I made one.
- tinier-py
- Table Of Contents
Python golfing is the challenge to write as little as possible amount of python code in order to achieve the goal or complete the quest. By playing Code golf you'll learn to reduce, reuse and recycle your python code. It's important that your code does not have to be readable. Your sole goal is to complete the challenge given.
The purpose of code golfing is to test one’s abilities, during challenges. That said, you should not use techniques like this in your normal code, as it compromises readability. Ideally, you should only use these tricks during a challenge.
~ tinier.js.org
Here are some platforms to play code golfing:
The main goal is to save as much characters as possible. Some Code Golfing competitions like clash of code actually support a neat shortcut for saving spaces, e.g. in the following scenarios:
[c if 1 == 1 else "0" for c in "Hello World!"]
this can be shorten to
[c if1==1else"0"for c in"Hello World!"]
This is already pretty neat and a nice advantage. But speaking in general, you shouldn't have spaces around mathematical operators, strings and parantheses. For example
print ( "Hello" + " " + "World" )
should not be done an can be written as
print("Hello"+" "+"World")
or even better:
print("Hello World")
Python gives you the abillity to use 1space instead of 4space. This can be seen in this example:
for x in range(10):
print(1)
As seen above, there is a tab-indentation used. This can take up to 4 characters. By using
for x in range(10):
print(1)
this you save 3 whole characters. If you have the possibillty, use
for x in range(10):print(1)
as well to save another 2 characters!
Let's say for example you have three lines of the given input e.g.
10
20
30
normally, you would write something like
# Longhand
a=int(input())
b=int(input())
c=int(input())
in order to retrieve all three of these numbers.
This can be minified by using open
with the file descriptor 0
which stands for stdin
:
# Shorthand
a,b,c=map(int,open(0).read().split())
open(0)
collects everything from the standard input. Its the same as reading a normal file in python. map
is used here to instantly convert these inputs to integers.
If you have at least three inputs, you have the abillity to shorten your function calls in characters. This
# Longhand
a=int(input())
b=int(input())
c=int(input())
can be shortened to
# Shorthand
I=input
a=int(I())
c=int(I())
d=int(I())
A typical check for prime you see on the internet is e.g.
# Longhand
if num > 1:
for i in range(2,num):
if (num % i) == 0:
print(num,"is not a prime number")
break
else:
print(num,"is a prime number")
else:
print(num,"is not a prime number")
This can be easily written in an onliner:
# Shorthand
print([i for i in range(2,num)if(num%i<1)]==[]and num>1)
This is quite simple but I've seen countless people forget this. Swap out your equal equal by using a less than symbol:
# Longhand
a==0
# Shorthand
a<1
This saves a lot! A character is much worth in code golfing.
Instead of using math.sqrt
:
# Longhand
import math
math.sqrt(int(input()))
# Shorthand
int(input())**0.5
The math library has two functions: floor
and ceil
:
# Longhand
import math
a = float(input())
print(math.floor(a/3))
print(math.ceil(a/3))
tho we can make use of some simple math to shorten this:
# Shorthand
a = float(input())
print(a//3))
print(-(-a//3))
When checking for an integer, we can compare the floored and the ceiled outcome of the number.
import math
a = float(input())
# Longhand
print(math.floor(a) == math.ceil(a))
# Shorthand by using modulo operator
print(a%1==0)
Let's assume we have to print true
when 1 is less than 2, otherwise we have to print false
. This could be solved by writing
print(str(1<2).lower())
this already a short solution. The problem is that sometimes, you don't have to print true
or false
but instead something like wrong
or right
. If you need to do that, mix both strings with each other and start with the longer string. E.g.
wrong
and right
gets to wrriognhgt
.
This may seem weird as first but we make use of the python string slicing function which gives us the abillity to skip certain indecies:
print('wrriognhgt'[1<2::2])
If the output seems kinda wrong, mix the string again but this time start with the other part.
If you have 2 input statements and one print statement:
# Longhand
a=input()
b=input()
print(a+b)
you can simplify that to:
# Shorthand
I=input
a=I()
b=I()
I(a+b)
This one is also an easy one. If you need to print two integers with a space in between, you could do:
# Longhand
print(str(a//b) + " " + str(b//a))
but we can use multiple arguments in python which are splitted by a seperator:
# Shorthand
print(a//b,b//a)
These things can take up a lot of characters of code when you don't know a shortcut for it. The challenge states that we should print the float when there is a number after the decimal point, otherwise just print the number itself without the decimal point and the leading zero. A way to do this would be:
# Longhand
my_float = str(...)
print(my_float.split(".")[0] if my_floats.endswith(".0") else my_float)
but a good shortcut for this would be to use Pythons Percentage formatting:
# Shorthand
print("%g"%(my_float))
If you need to seperate a list of numbers, don't use join:
# Longhand
print(', '.join(['A', 'B']))
use a starred expression and the sep
argument of the print function
# Shorthand
print(*['A','B'],sep=', ')
As already mention above, you can use starred expressions in print statements to unpack every number of an interable or geneartor. Normally, this would seem like:
# Longhand
print(" ".join(map(..., [0,1,2,3,4,5,6])))
but you can add an asterik before the map
method which unpacks every value. (Also, you can map iterators as well)
# Shorthand
print(*map(...,range(7)),sep=" ")
You can achieve this by writing
# Longhand
l1 = [1, 2, 3, 4, 5]
for i in range(len(l1)):
if i != len(l1) - 1:
val1 = l1[i]
val2 = l1[i+1]
but a much much shorter way of this would be by using the zip
method, which returns a list containing tuples:
# Shorthand
l1 = [1, 2, 3, 4, 5]
for val1, val2 in zip(l1, l1[1:])
Converting an iterator like map
to a list can be achieved by
# Longhand
list(map(...))
# Shorthand by using starred expressions
[*map(...)]
Let's say you need a list of the numbers in a range from 0 to 2, you could use range(3) and convert it to a list:
A = list(range(3))
but again, there are these wonderful starred expressions:
*A=range(3)
Retrieving the last element can be done by accessing the negative one index
# Longhand
L = [1, 2, 3, 4]
a=L[-1]
but we can just use the starred expression here again:
# Shorthand for the last element
L = [1, 2, 3, 4]
*_,a=L
this can also be done as well for the first element:
# Shorthand for the first element
L = [1, 2, 3, 4]
a,*_=L
Python has gotten the pop method. This example is a bit bad but I think you can think of a use case
L = [1, 2, 3, 4]
# Longhand
L.pop(0)
# Shorthand
# Popping the first index
_,*L=L
# Removing the last index
*L,_=L
what we do here is unpacking the list L
to the variables _
and L
. The underscore stands for a non-used variable.
When having the following code
# Longhand
print(sum(list(map(lambda e:e+1,[1,2,3,4,5,6]))))
you can remove the list function. sum
can also sum iterators as well! And also, you might be noticing that the __add__
method is used instead of a lambda. This is also shorter as well.
# Shorthand
print(sum(map(int(1).__add__,[1,2,3,4,5,6])))
Combine two foor loops into one:
# Longhand
for x in range(a):
for y in range(b):
print(x, y)
# Shorthand
for xy in range(a*b):
x = xy//a
y = xy%a
# Longhand
for x in range(3):
print(x)
# Shorthand
for x in 0,1,2:
print(x)
# Longhand
for _ in range(10):
print(1)
# Shorthand
for _ in[1]*10:
print(1)
You can replace a for loop with a range when the current iteration count does not matter with the use of the eval
function.
# Longhand
for _ in range(n):
print(1)
# Shorthand
exec('print(1);'*n)
# Longhand
for i in range(2):
for j in range(3):
for k in range(4):
print(i,j,k)
# Shorthand
for k in range(2*3*4):
print(k//3//4, k%(3*4), k%4)
# Longhand
i-=1
i+=1
# Shorthand (Bit flipping)
~-i
-~i
S = {1, 2, 3, 4, 5, 6}
# Longhand (set)
print(5 in S)
# Shorthand
print({5}&S)
# Longhand
print(a and b)
# Shorthand
print(a&b)
# Shorthand number 2
print(a*b)
# Longhand
print(a or b)
# Shorthand
print(a|b)
A = [...]
B = 3
# Longhand
A.append(B)
# Shorthand
A+=B,
A = [...]
B = [...]
# Longhand
A.extend(B)
# Shorthand
A+=B
# Longhand
if a > 0 and a < 10:
print(a)
# Shorthand
if 0<a<10:
print(a)
# Longhand
if a > 10 and b > 10 and a < 30 and b < 50:
print(a, b)
if 50 > b > 10 < a < 50:
print(a, b)
# Longhand
def c(a):
if a < 3: return a - 5
else: return a + 5
# Shorthand
c=lambda a:a<3and a-5or a+5
# Longhand
alphabet = 'abcdefghijklmnopqrstuvwxyz'
# Shorthand
alphabet = map(chr,range(97,123))
# Longhand
if a < b: return a
else: return b
# Shorthand
return (b,a)[a<b]
string = "clashofcode"
# Longhand
for i in range(len(string)-1,-1,-1):
print(string[i])
# Shorthand
for i in string[::-1]:
print(i)
# Even Shorter
print(string[::-1))
# Longhand
a = 0
b = 0
c = 0
# Shorthand
a,b,c=0,0,0
# Even Shorter
a=b=c=0
# And for strings
a,b,c='pqr'
# And for lists
a,b,c=[1,'abc',True]
L = (1,2,3,4,5)
# Longhand
A = list(L)
# Shorthand
A=[*L]
# Even Shorter
*A,=L
L=[1,2,3,4,5]
# Longhand
x = set(L)
# Shorthand
x={*L}
L=[1,2,3,4,5,6]
# Longhand
a = tuple(L)
# Shorthand
a=(*L,)
T=[*range(10)]
# Longhand
T = [1] + T + [10]
# Shorthand
T = [1,*T,10]
# Same with tuples
T = (1,*T,10)
word = input()
print([c for c in word if c.isupper()])
can be written as
import re
word=input()
print(re.sub('[^A-Z]','',word))
print(x == 5 and y == 6)
can be written as
print((x,y)==(5,6))