Generating all possible permutations (ordered arrangements) of a set of digits is a classic problem in combinatorics and programming. Given three digits like 1, 2, and 3, the goal is to produce every unique ordering: [1, 2, 3], [1, 3, 2], [2, 1, 3], and so on. This is useful in password generation, puzzle solving, brute-force algorithms, and combinatorial analysis.
In this guide, you will learn multiple methods to generate all permutations of three digits in Python, from the built-in itertools.permutations to recursive and loop-based approaches, along with explanations of how each method generalizes to more than three elements.
Understanding Permutations vs. Combinations
Before diving in, it's important to clarify the terminology:
- Permutations: order matters:
[1, 2, 3]and[3, 2, 1]are different. - Combinations: order doesn't matter:
{1, 2, 3}and{3, 2, 1}are the same.
For n elements, the number of permutations is n! (n factorial):
- 3 digits → 3! = 6 permutations
- 4 digits → 4! = 24 permutations
- 5 digits → 5! = 120 permutations
Method 1: Using itertools.permutations (Recommended)
The most efficient and Pythonic approach uses itertools.permutations, which generates all ordered arrangements:
from itertools import permutations
digits = [1, 2, 3]
for perm in permutations(digits):
print(perm)Output:
(1, 2, 3)
(1, 3, 2)
(2, 1, 3)
(2, 3, 1)
(3, 1, 2)
(3, 2, 1)Collecting Results as a List
from itertools import permutations
digits = [1, 2, 3]
all_perms = [list(p) for p in permutations(digits)]
print(f"Total permutations: {len(all_perms)}")
for p in all_perms:
print(p)Output:
Total permutations: 6
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]Generating Partial Permutations
You can also generate permutations of a specific length from a larger set:
from itertools import permutations
digits = [1, 2, 3, 4]
for perm in permutations(digits, 2):
print(perm)Output:
(1, 2)
(1, 3)
(1, 4)
(2, 1)
(2, 3)
(2, 4)
(3, 1)
(3, 2)
(3, 4)
(4, 1)
(4, 2)
(4, 3)Method 2: Using Recursion
A recursive approach builds permutations by fixing one element at a time and recursively permuting the remaining elements:
def get_permutations(elements, current=[]):
"""Recursively generate all permutations."""
if len(current) == len(elements):
print(current)
return
for item in elements:
if item not in current:
get_permutations(elements, current + [item])
digits = [1, 2, 3]
get_permutations(digits)Output:
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]How it works:
- Base case: When the
currentlist has the same length as the input, a complete permutation is formed: print it. - Recursive case: For each element not yet in
current, add it and recurse with the extended list. - The
item not in currentcheck ensures each element is used exactly once.
Improved Recursive Version with Swapping
A more efficient recursive approach swaps elements in place:
def permute(arr, start=0):
"""Generate permutations by swapping elements in place."""
if start == len(arr):
print(arr[:]) # Print a copy
return
for i in range(start, len(arr)):
arr[start], arr[i] = arr[i], arr[start] # Swap
permute(arr, start + 1) # Recurse
arr[start], arr[i] = arr[i], arr[start] # Backtrack
digits = [1, 2, 3]
permute(digits)Output:
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 2, 1]
[3, 1, 2]This approach avoids creating new lists at each step, using O(1) extra space (not counting the recursion stack).
Method 3: Using Nested Loops (Fixed for Three Elements)
For exactly three elements, three nested loops with distinctness checks produce all permutations:
digits = [1, 2, 3]
for i in range(3):
for j in range(3):
for k in range(3):
if i != j and j != k and i != k:
print(digits[i], digits[j], digits[k])Output:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1How it works:
- Three nested loops iterate over all possible index combinations.
- The condition
i != j and j != k and i != kensures all three indices are distinct. - Only valid permutations (where no element repeats) are printed.
Generating Permutations as Numbers
If you need the permutations as three-digit numbers (e.g., for PIN generation):
from itertools import permutations
digits = [1, 2, 3]
numbers = []
for perm in permutations(digits):
number = int("".join(str(d) for d in perm))
numbers.append(number)
print("All three-digit numbers:", sorted(numbers))Output:
All three-digit numbers: [123, 132, 213, 231, 312, 321]Handling Duplicate Digits
When the input contains duplicate digits, itertools.permutations treats them as distinct (by position), producing duplicate results:
Problem
from itertools import permutations
digits = [1, 1, 2]
for perm in permutations(digits):
print(perm)Output (contains duplicates):
(1, 1, 2)
(1, 2, 1)
(1, 1, 2) ← duplicate
(1, 2, 1) ← duplicate
(2, 1, 1)
(2, 1, 1) ← duplicateFix: use set() to eliminate duplicates
from itertools import permutations
digits = [1, 1, 2]
unique_perms = set(permutations(digits))
for perm in sorted(unique_perms):
print(perm)Output:
(1, 1, 2)
(1, 2, 1)
(2, 1, 1)Practical Example: Generating All PIN Combinations
from itertools import permutations
digits = [3, 7, 9]
print("All possible 3-digit PINs:")
for perm in permutations(digits):
pin = "".join(str(d) for d in perm)
print(f" {pin}")
print(f"\nTotal PINs: {len(list(permutations(digits)))}")Output:
All possible 3-digit PINs:
379
397
739
793
937
973
Total PINs: 6Comparison of Methods
| Method | Generalizable | Performance | Handles Duplicates | Best For |
|---|---|---|---|---|
itertools.permutations |
✅ Any n | ✅ Fastest (C impl.) | ⚠️ With set() |
Production code (recommended) |
| Recursion | ✅ Any n | ⚠️ Moderate | ⚠️ With checks | Learning, custom logic |
| Recursion (swap) | ✅ Any n | ✅ Fast (in-place) | ⚠️ With checks | Memory-efficient |
| Nested loops | ❌ Fixed n only | ✅ Fast | ✅ Yes | Small, fixed-size inputs |
Summary
Generating all permutations of three (or more) digits in Python can be accomplished in several ways:
- Use
itertools.permutations()for the simplest, fastest, and most flexible solution: it works with any number of elements and is implemented in optimized C code. - Use recursion for educational purposes or when you need custom logic during permutation generation (e.g., pruning, filtering).
- Use nested loops for quick, fixed-size problems where the number of elements is known and small (2–4 elements).
- Handle duplicates by wrapping results in
set()when input elements may repeat.
For n elements, there are n! permutations: this grows very quickly (10! = 3,628,800), so be mindful of performance and memory when working with larger inputs.