Algorithm to iterate through sample space of numbers
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Iterating through a sample space of numbers means generating every possible outcome that satisfies a set of rules. The right algorithm depends on whether order matters, whether repetition is allowed, and whether you want to process results one at a time or store them all in memory.
Define the Sample Space First
Before choosing an algorithm, write down the exact rules. These three problems look similar but produce different result sets:
- all sequences of length
3from digits0through2, with repetition allowed - all permutations of three distinct numbers
- all combinations where order does not matter
For example, if the domain is [0, 1, 2] and length is 2:
- sequences with repetition:
(0,0),(0,1),(0,2),(1,0)and so on - permutations without repetition:
(0,1),(0,2),(1,0)and so on - combinations without repetition:
(0,1),(0,2),(1,2)
The algorithm must match the mathematical meaning of the sample space.
Use Recursive Backtracking for General Generation
Backtracking is a flexible way to generate outcomes. It builds one partial result, extends it, then undoes that choice and tries the next option.
This Python generator produces all length-k sequences with repetition allowed:
This works well because:
- it avoids writing a different number of nested loops for each length
- it can generate results lazily
- the same structure adapts to permutations and combinations
If repetition is not allowed, skip values already in current:
For large spaces, using a generator is important because it yields one outcome at a time instead of building an enormous list first.
Use Start Indices for Combinations
When order does not matter, you should not generate both (1,2) and (2,1). A common fix is to carry a start index and only explore later values.
This avoids duplicates by construction. That is better than generating all permutations and filtering later.
Think About Complexity Early
Sample spaces grow fast. With n values and sequence length k:
- sequences with repetition have
n^koutcomes - permutations have
n! / (n-k)!outcomes - combinations have
n! / (k! * (n-k)!)outcomes
That growth is the real bottleneck, not the specific syntax of the loop. If you generate every possibility, runtime is at least proportional to the number of outcomes.
Because of that, practical algorithms often do one of two things:
- yield results lazily so memory stays bounded
- prune branches early when a partial result already violates a rule
Pruning can turn an impossible brute-force search into a reasonable one when constraints are strong.
When Iteration Is Really Search
Many problems described as "iterate through a sample space" are actually search problems. You do not want every outcome; you want the first valid outcome or the best one. In those cases, stop as soon as your goal is reached instead of collecting the full sample space.
For example, if the sum of the numbers must equal 10, you can check the partial sum during backtracking and skip branches that already exceed 10. That changes the practical runtime dramatically.
Common Pitfalls
The biggest mistake is using the wrong sample-space definition. If order does not matter, generating permutations creates duplicates and unnecessary work.
Another common issue is storing every result in a list. That is fine for tiny spaces, but sample spaces often grow exponentially. Prefer generators unless you truly need the full collection in memory.
Be careful with membership checks such as if value in current for large inputs. They are simple and readable, but they add extra overhead. For performance-sensitive code, a separate used set or boolean array can be better.
Finally, do not confuse brute-force enumeration with an optimized solver. If the problem has constraints, exploit them during generation instead of filtering after the fact.
Summary
- Start by defining whether order matters and whether repetition is allowed.
- Recursive backtracking is a general way to iterate through numeric sample spaces.
- Use a
startindex for combinations so duplicate orderings are never generated. - Prefer generators when the sample space is large.
- Add pruning early when the real goal is search rather than full enumeration.

