Code Golf Techniques — Deep Dive

The competitive landscape

Python consistently ranks in the top five languages on code-golf sites. Its concise syntax, rich standard library, and duck typing make it naturally terse. However, dedicated golf languages like Jelly, 05AB1E, and Pyth are even shorter for most problems. Python golfers compete not for absolute shortest solutions but for the shortest within general-purpose languages — and for the elegance of exploiting a well-known language in unexpected ways.

Advanced byte-saving techniques

Import minimisation

Standard library imports cost bytes. Strategies to minimise them:

# Full import (17 bytes)
from math import*
# Access without import via __import__ (saves when you need one function)
__import__('math').gcd(12,8)
# But for multiple uses, the import statement wins

For re, a common pattern:

# 16 bytes
import re;re.sub
# 15 bytes using __import__
__import__('re').sub
# But if you use re.sub multiple times:
import re;s=re.sub  # assign to short name

exec with string compression

For repetitive output, compress the program as a string:

exec(bytes(range(33,127)).decode())  # execute ASCII art as code

More practically, use exec to avoid def/return:

# Instead of:
def f(n):
 for i in range(n):print(i)
f(10)

# Use:
exec("for i in range(10):print(i)")

Recursive lambda with default arguments

Python lambdas cannot use statements, but recursion via default-argument binding is a classic trick:

# Factorial in 28 bytes
f=lambda n:n<2or n*f(n-1)

For problems requiring a helper variable:

# Fibonacci sequence
f=lambda n,a=0,b=1:n and f(n-1,b,a+b)or a

The default arguments a=0,b=1 serve as state accumulators. Each recursive call shifts the window.

Abusing or and and as control flow

Python’s short-circuit evaluation turns boolean operators into conditional expressions:

# Instead of: x if condition else y
# Use (when x is truthy):
condition and x or y

# Print only if condition:
condition and print("yes")

Caveat: this fails when x is falsy (0, empty string). The ternary x if c else y is safer but costs more characters.

Integer-to-string and back

# Convert list of digits to number
int("".join(map(str,digits)))
# Shorter:
int(''.join(str(d)for d in digits))  # actually longer
# Shortest for known range:
eval(''.join(map(str,digits)))  # same length but works for expressions too

For base conversion:

# Decimal to binary string
bin(42)      # '0b101010'
f"{42:b}"    # '101010' — no prefix, 7 bytes shorter in context

itertools golf

itertools functions replace verbose loops:

from itertools import*

# All permutations
[*permutations("abc")]

# Cartesian product (replaces nested loops)
[*product(range(3),repeat=2)]

# Accumulate (running sum without a loop)
[*accumulate(range(10))]

The from itertools import* costs 22 bytes. It pays off when you use two or more functions from the module.

Encoding and output tricks

chr and ord manipulation

Building strings character by character is sometimes shorter than string literals:

# "Hello" is 7 bytes (with quotes)
# chr-based might be longer... but for non-printable or repetitive patterns:
''.join(chr(i)for i in[72,101,108,108,111])

More useful: generate alphabets without typing them:

# All lowercase letters
[chr(i)for i in range(97,123)]
# Shorter with map:
[*map(chr,range(97,123))]
# Print space-separated list
print(*[1,2,3])      # "1 2 3"
# Print with custom separator
print(*[1,2,3],sep='\n')  # one per line
# Suppress newline
print(x,end='')

Starred unpacking in print

# Instead of:
for x in range(5):print(x)
# Use:
print(*range(5),sep='\n')

This replaces a two-line loop with a single expression.

Algorithmic tricks

Mathematical replacements

Many conditional patterns have mathematical equivalents:

# Absolute value without abs()
(x,-x)[x<0]   # but abs(x) is only 6 bytes — not always a win

# Clamp to non-negative
x*(x>0)

# Sign function
(x>0)-(x<0)

# Ceiling division
-(-a//b)

String multiplication for patterns

# Triangle of stars
for i in range(1,6):print("*"*i)

# Checkerboard
for i in range(8):print(("# "*8)[i%2:16])

Set operations for uniqueness

# Unique elements preserving order
dict.fromkeys(lst)  # Python 3.7+ dicts preserve insertion order
# Shorter than list(set(lst)) when order matters

Platform-specific tricks

Reading input efficiently

# Multiple lines of input
import sys;L=sys.stdin.read().split('\n')
# Shorter:
L=open(0).read().split('\n')
# Even shorter for line-by-line:
L=[*open(0)]

open(0) opens file descriptor 0 (stdin). This is the shortest way to read all input in Python golf.

Recursion limit

For recursive solutions on large inputs:

import sys;sys.setrecursionlimit(9**9)

This costs 41 bytes. For problems where iteration is possible, it is usually shorter to avoid recursion entirely.

Competitive strategy

Step 1: Solve correctly first

Write a clear, correct solution. Count its bytes.

Step 2: Identify the expensive parts

What costs the most bytes? A long import? A multi-line loop? A verbose conditional? Attack the biggest cost first.

Step 3: Look for built-in replacements

Python’s sum, min, max, sorted, zip, map, filter, any, all, enumerate — each replaces a loop pattern in fewer bytes.

Step 4: Flatten control flow

Replace if/elif/else chains with dictionary lookups, conditional expressions, or arithmetic. Replace for loops with map or comprehensions. Replace while loops with recursive lambdas.

Step 5: Micro-optimise

  • Remove spaces around operators (Python allows 1+2 not 1 + 2 in golf context)
  • Use ; to merge lines
  • Replace True/False with 1/0
  • Replace not x with 1-x when x is boolean
  • Use ~x for -(x+1) in indexing: a[~0] is a[-1]

Tradeoffs and ethics

BenefitCost
Deep language masteryUnreadable output
Creative problem-solving practiceBad habits if applied to production
Community and competitionTime-consuming for diminishing returns
Exposure to obscure stdlib functionsVersion-dependent tricks may break

Code golf explicitly violates every clean-code principle. That is the point. The skill is knowing when to golf and when to write for humans. The best golfers are often excellent production programmers because they understand the language at a level most developers never reach.

One thing to remember: The shortest Python solution to a problem reveals the language’s hidden expressiveness. Studying golf solutions — even if you never compete — teaches you corners of Python that years of normal use might never expose.

pythonpuzzlesprogramming-challenges

See Also

  • Ci Cd Why big apps can ship updates every day without turning your phone into a glitchy mess — CI/CD is the behind-the-scenes quality gate and delivery truck.
  • Containerization Why does software that works on your computer break on everyone else's? Containers fix that — and they're why Netflix can deploy 100 updates a day without the site going down.
  • Python 310 New Features Python 3.10 gave programmers a shape-sorting machine, friendlier error messages, and cleaner ways to say 'this or that' in type hints.
  • Python 311 New Features Python 3.11 made everything faster, error messages smarter, and let you catch several mistakes at once instead of stopping at the first one.
  • Python 312 New Features Python 3.12 made type hints shorter, f-strings more powerful, and started preparing Python's engine for a world without the GIL.