Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Riley edited this page Jan 18, 2026 · 29 revisions

Packers

A 2:1 packer

This is Python's fabled 2:1 packer, for your convenience. For chars scoring, it can reduce code by a factor of two.

Spoiler

Decompressor

Note: the overhead is 25 characters so your uncompressed code must be over 50 characters to get a benefit.

exec(bytes('...','u16')[2:])

Compressor

Note: the code size must be divisible by 2 for the compressor to work. If not, adding a trailing space should suffice.

print('CODE'.encode().decode('u16'))

A 3:1 packer

There also exists a 3:1 packer, but it only works with bytes above ASCII character 31.

Spoiler

Decompressor

Note: the overhead is 49 characters so your uncompressed code must be over 73 characters to get a benefit over unpacked code and over 144 characters to get a benefit over the 2:1 packer (assuming a compression ratio of strictly 3:1).

exec(bytes(ord(c)%i+32for c in'...'for i in b'efg'))

Compressor

def crt(a, n):
	s, p = 0, 1
	for x in n:
		p *= x
	for x, y in zip(a, n):
		q = p // y
		s += q * x * pow(q, -1, y)
	return s % p

code = '''CODE'''

compressed = ''
for i in range(0, len(code), 3):
	a = [ord(c) - 32 for c in code[i:i+3]]
	compressed += chr(crt(a, [101, 102, 103]))

print(compressed)

Boolean access

Instead of:

a if condition else b

Use:

[b,a][condition]

Only works if a and b can both be safely evaluated, regardless of which one is picked.

Shorter if...else

As seen above, [b,a][condition] may be used instead of an if...else, but only if a and b cause no side effects. A laxer alternative is

condition and a or b

It saves one byte, but has the restriction that a must be truthy. There is also

a*condition or b

but with this one, a must be truthy, in addition to not causing any side effects.

Chained comparison

Use comparison chaining to save bytes on and:

0<a and a<5 and 0<b and b<5
# vs
0<a<5 and 0<b<5
# vs
0<a<5>b>0

You can chain in as well. This is less useful, but nice to know:

a in b and b<c
# vs
a in b<c

The next tip on short circuiting also utilizes comparison chaining.

Short circuiting ==

if f(x)>1:print(x)

can be rewritten implementing the short circuit:

f(x)>1==print(x)

Multiple assignment

If you need to assign multiple variables to the same value, it's better to combine them into one statement:

a=1;b=1
# vs
a=b=1

However, assigning to an object (such as a list) may result in some weird behavior, since all the variables share the same instance:

a=b=[]
a.append(1)
print(a,b)
>>> [1] [1]

Appending to a list

By creating a tuple, you can do += instead of append, saving 6 bytes:

a.append(b)
# vs
a+=b,

This can be be used with slicing to replace insert:

a.insert(i,b)
# vs
a[:i]+=b,

Walrus operator

Python 3.8 introduced assignment expressions (A.K.A. the walrus operator). Its main use in golf is to allow assigning and using a variable at the same time:

while 1:x=1;...
# vs
while x:=1:...

x=1;f(x);g(x)
# vs
f(x:=1);g(x)

Using byte strings as integer lists

Python's byte strings can act like integer lists, sometimes:

[48,96,33]
# vs
b'0`!'

This can, for example, help with iterating or indexing a list:

# Iteration
for x in 48,96,33:
for x in b'0`!':

# Indexing
[48,96,33][i]
b'0`!'[i]

Unpacking assignment

Here is a list of tricks for potentially saving bytes on variable assignment. All are based on the powerful feature of iterable unpacking:

  • Swapping two variables
t=a;a=b;b=t
# vs
a,b=b,a
  • Unpacking an iterable
a=L[0];b=L[1];c=L[2]
# vs
a,b,c=L
  • Assigning a value + a list
x=1;L=[1]
# vs
x,=L=[1]
  • Assigning a value + an empty list
x=1;L=[]
# vs
x,*L=1,
  • Converting an iterable to a list
L=list(range(5))
# vs
*L,=range(5)
  • Popping off the first element of a list
x=L.pop(0)
# vs
x,*L=L
  • Popping off the last element of a list
x=L.pop()
# vs
*L,x=L

Print list separated by \n

AFAIK, the shortest way to print a list (or any iterator) with each element on a new line is:

*map(print,L),

Some longer alternatives include:

[*map(print,L)]
*_,=map(print,L)
0in map(print,L)
print(*L,sep='\n')
for x in L:print(x)

Print variables in one line

Sometimes there is a need to print series of incoming variables (not a list) in one line. Normally, it is done in such a way:

print(variable,end="")

There is a shorter version for that:

print(end=variable)

Splat on iterables

Splat makes functions like list, set, and tuple a lot shorter:

list(L)  -> [*L]
tuple(T) -> (*T,)
set(S)   -> {*S}

It saves on concatenation as well:

[1,2]+[L]+[3,4] -> [1,2,*L,3,4]
(1,2)+L+(3,4)   -> (1,2,*L,3,4)

A sys.argv trick

Some of the holes on code.golf require input through ARGV. Nine out of ten times,

for a in sys.argv[1:]:f(a)

will be the shortest option. But let's take a look at this alternative:

while 1:f(sys.argv.pop(1))

Both of these contain the same amount of bytes, except the second one is less useful as it is not stored in a variable. The advantage with the second option is that the while 1 might have room to fit a walrus operator (as discussed in this tip). Under these specific circumstances, it can usually save one byte.

Removing multiple imports

Suppose you want functions x and y from modules a and b. It may just so happen that a itself imports b, wherein you can write

import a
a.x()
a.b.y()

This will work so long as a does not del b in its own code. If "b" appears in a.__all__, you can also use

from a import*
x()
b.y()

Bytes formatting

The % operator works on bytes too - b'%r'%x and b'%d'%x are really useful.

Hash

In Python 3, the hash function is still deterministic on tuples - so you can get an easy hash like this: hash((*b'%r'%x,)).

Incrementing/Decrementing

Suppose you want to do x+1 or x-1 and you have to put parenthesis around the expression or you have to put a space to the left of it. You can use binary not and negation to save up to 2 bytes.

(x+1) -> -~x
(x-1) -> ~-x

Another common example to save 1 byte.

while~99+x:
while x<100: 

Clone this wiki locally

Morty Proxy This is a proxified and sanitized view of the page, visit original site.