Counting Operations
An operation is a single fundamental action your computer performs. Assignment, arithmetic, comparison, and array access each count as one operation. To predict how fast your code runs, count how many operations it executes.
What is an Operation?
Your computer processes code one step at a time. Common operations include assignment (x = 10), reading a variable, arithmetic (+, -, *, /), comparisons (<, >, ==), array access (arr[i]), and function calls. Each represents a single fundamental action.
Use the counter below to explore this: set an input size n, compare how three shapes of code add up, and click any row to see its code with each line's operation count marked.
Each operation counts once: variable assignment takes one operation, reading a variable and using it in arithmetic counts as two, and comparison and array access each count as one.
Counting in Simple Code
Consider a function that calculates an average. The first three lines assign variables—three operations. The sum calculation reads three variables, performs two additions, and assigns the result—six operations. The division reads the sum, divides, and assigns—three operations. The return statement adds one more. Total: thirteen operations inside the function, plus one for calling it.
1def calculate_average():
2 a = 10 # 1 operation
3 b = 20 # 1 operation
4 c = 30 # 1 operation
5 sum_val = a + b + c # 6 operations (read a, read b, read c, add twice, assign)
6 avg = sum_val / 3 # 3 operations (read sum_val, divide, assign)
7 return avg # 1 operation
8# Total: 13 operations
Loops Multiply Operations
A loop runs its body multiple times. If the body contains k operations and the loop runs n times, the total operation count is approximately n × k.
A loop that runs n times executes the operations inside its body on every iteration. The operations outside the loop run once; the operations inside multiply by the number of iterations. (The Single loop row in the counter above shows this as 3n + 3.)
Consider a function that sums an array. Getting the array length takes one operation. Initializing the total takes another. The loop runs n times. Each iteration reads an array element, adds it to the total, and stores the result—three operations per iteration (we simplify by not counting every read). The return statement adds one more. Total: 1 + 1 + (3 × n) + 1 = 3n + 3 operations.
1def sum_array(arr):
2 n = len(arr) # 1 operation
3 total = 0 # 1 operation
4 for i in range(n):
5 total += arr[i] # 3 operations per iteration
6 return total # 1 operation
7# Total: 3n + 3 operations
Nested Loops
Nested loops multiply operations across all levels. An outer loop running n times with an inner loop running n times creates n × n iterations. If each iteration has k operations, the total is n × n × k.
Picture nested loops as a grid: the outer loop runs n times, and for each outer iteration the inner loop runs n times, creating n² total iterations. Each cell is one execution of the inner loop body. (The Nested loops row in the counter above shows this as 3n² + 1.)
Consider a function that prints all pairs from an array. Getting the array length takes one operation. The outer loop runs n times. For each outer iteration, the inner loop runs n times. Each inner iteration reads two array elements and prints them—three operations. Total: 1 + (n × n × 3) = 3n² + 1 operations. For n = 5, this equals 76 operations. For n = 10, this jumps to 301 operations.
1def print_pairs(arr):
2 n = len(arr) # 1 operation
3 for i in range(n):
4 for j in range(n):
5 print(arr[i], arr[j]) # 3 operations
6# Total: 3n² + 1 operations
7# n=5: 76 operations
8# n=10: 301 operations
Operation Count Growing with Input Size
Set n = 100 in the counter above and compare the rows. Straight-line code stays at 13 operations no matter what. The single loop grows linearly—doubling the input doubles the count. The nested loop grows quadratically—doubling the input quadruples it, past 30,000 operations at n = 100. That widening gap between linear and quadratic is the whole point of counting.
Why We Count
Counting operations predicts performance before running code. Comparing two algorithms shows which runs faster. Identifying bottlenecks reveals which parts slow down the program. This knowledge guides choosing the right approach for each problem.
Exact counts matter less than understanding growth. Does the count stay constant as input grows? Does it grow linearly with input size? Does it grow quadratically? Constant is best. Linear works well for most problems. Quadratic gets slow quickly. Exponential only handles tiny inputs.
The next lesson introduces Big-O notation, which formalizes this idea by categorizing algorithms based on their growth rate.