Counting Operations
When you write code, your computer executes it one operation at a time. To predict how fast your code will run, you need to count how many operations it performs. This is the foundation of understanding algorithm speed.
What is an Operation?
An operation is a single, fundamental action your computer performs. Common operations include:
- Variable assignment:
x = 10 - Reading a variable: Using
xin an expression - Arithmetic:
+,-,*,/ - Comparisons:
<,>,==,!= - Array access:
arr[i] - Function calls:
print(),len() - Return statements:
return result
Let's count operations in simple code:
In this example, we have 9 operations total. Each line of code may contain one or more fundamental operations.
Counting in Simple Code
Let's practice counting operations with a simple example:
1def calculate_average():
2 a = 10 # 1 operation: assignment
3 b = 20 # 1 operation: assignment
4 c = 30 # 1 operation: assignment
5 sum = a + b + c # 4 operations: read a, read b, read c, add
6 avg = sum / 3 # 3 operations: read sum, divide, assignment
7 return avg # 1 operation: return
8
9result = calculate_average() # 1 + 11 operations (call + function body)
10# Total: 12 operations
Loops Multiply Operations
When you use a loop, the operations inside the loop body run multiple times. This multiplies the operation count.
Key principle: If a loop runs n times and has k operations inside, the total operation count is approximately n × k.
Let's see this in action:
1def sum_array(arr):
2 n = len(arr) # 1 operation
3 total = 0 # 1 operation
4
5 # Loop runs n times
6 for i in range(n):
7 total += arr[i] # 3 operations per iteration:
8 # 1. read arr[i]
9 # 2. read total
10 # 3. add and store
11
12 return total # 1 operation
13
14# Total: 1 + 1 + (3 × n) + 1 = 3n + 3 operations
Nested Loops
When you have nested loops (a loop inside another loop), operations multiply even more dramatically.
Key principle: If the outer loop runs n times and the inner loop runs m times for each outer iteration, the total operation count is approximately n × m × k, where k is the number of operations in the innermost body.
Let's count operations in nested loops:
1def print_pairs(arr):
2 n = len(arr) # 1 operation
3
4 # Outer loop runs n times
5 for i in range(n):
6 # Inner loop runs n times (for each outer iteration)
7 for j in range(n):
8 print(arr[i], arr[j]) # 3 operations:
9 # 1. read arr[i]
10 # 2. read arr[j]
11 # 3. print
12
13# Total: 1 + (n × n × 3) = 3n² + 1 operations
14# For n=5: 3 × 25 + 1 = 76 operations
Practice Examples
Let's compare how operation counts grow with different code patterns:
Example 1: Constant Operations
1x = 5
Operation count: 1 (always the same, regardless of input size)
Example 2: Linear Operations (Loop)
1for i in range(n):
2 total += i
Operation count: 3n + 2 (grows proportionally with n)
- If n = 1: ~5 operations
- If n = 5: ~17 operations
- If n = 100: ~302 operations
Example 3: Quadratic Operations (Nested Loop)
1for i in range(n):
2 for j in range(n):
3 print(i, j)
Operation count: n² (grows with the square of n)
- If n = 1: 1 operation
- If n = 5: 25 operations
- If n = 10: 100 operations
- If n = 100: 10,000 operations
Notice how nested loops explode in operation count! This is why understanding loops is crucial for writing fast code.
Why We Count
Counting operations helps us:
- Predict performance: Estimate how long code will take before running it
- Compare algorithms: Determine which approach is faster
- Find bottlenecks: Identify which parts of code are slow
- Make informed decisions: Choose the right data structure and algorithm for the problem
Important insight: We don't need exact operation counts. What matters is understanding how the count grows as input size increases:
- Does it stay constant? (Great!)
- Does it grow linearly? (Good for most problems)
- Does it grow quadratically? (Gets slow quickly)
- Does it grow exponentially? (Only works for tiny inputs)
In the next lesson, we'll formalize this idea with Big-O notation to categorize algorithms by their growth rate.
Key Takeaways
- An operation is a single fundamental action (assignment, arithmetic, comparison, array access, etc.)
- Simple code: Count each operation (usually constant)
- Loops: Operations inside × number of iterations
- Nested loops: Multiply operations across all loop levels
- Growth matters: How operation count scales with input size determines performance
- Nested loops are expensive: They can quickly create thousands or millions of operations
Understanding operation counting is the first step toward analyzing algorithm efficiency!