20. Loop patterns

Almost every loop is one of four shapes. Name them and you stop inventing each loop from scratch — you reach for the one that fits. The four are accumulate, count, search, and flag, each doing one small job. The examples use a range of numbers, but the shapes work on anything you can loop over.

1. Accumulate — build up a result

Hold a variable and change it every turn. The running total is the classic case:

local sum = 0
for i = 1, 10 do
    sum = sum + i
end
print(sum)       -- 55

The shape is always: set a start value before the loop, update it inside, use it after. It also builds strings (start "", glue on each piece) and finds a maximum (start low, raise it whenever you see something bigger).

2. Count — how many match?

A counter is an accumulator that goes up by one, but only when a test passes. "How many numbers from 1 to 30 divide evenly by 3?"

local hits = 0
for i = 1, 30 do
    if i % 3 == 0 then
        hits = hits + 1
    end
end
print(hits)      -- 10

The if inside the loop is the test; hits = hits + 1 is the tally.

3. Search — find the first match and stop

When you only need the first value that fits, break out the moment you find it — no point continuing:

local first
for i = 1, 100 do
    if i * i > 50 then
        first = i
        break
    end
end
print(first)     -- 8   (because 8 × 8 = 64, the first square over 50)

first starts as nil. If nothing matched, it stays nil — a handy "not found" answer you can test with if.

4. Flag — did any turn match?

Sometimes you want a yes/no, not the value: "is any number from 1 to 20 divisible by 7?" Keep a boolean that starts false and flips to true the moment you see a match:

local found = false
for i = 1, 20 do
    if i % 7 == 0 then
        found = true
    end
end
print(found)     -- true   (7 and 14 are in range)

If you only care whether one exists, break when the flag flips — that turns it into a search. Flag and search are cousins.

Open exercises/20/01-patterns.lua. It accumulates the sum of 1 to 20. Add the count pattern below it to print how many numbers in that range are even.

Mixing the patterns

Real programs combine these. One pass can accumulate a total, count how many fit a rule, and flag whether something special appeared, all at once:

local total = 0
local evens = 0
local has_multiple_of_5 = false

for i = 1, 10 do
    total = total + i                       -- accumulate
    if i % 2 == 0 then evens = evens + 1 end -- count
    if i % 5 == 0 then has_multiple_of_5 = true end  -- flag
end

print("total", total)              -- 55
print("evens", evens)              -- 5
print("multiple of 5?", has_multiple_of_5)  -- true

One loop, three patterns, three answers.

Homework

Homework files are in exercises/20/homework/.

Problem 1 — Factorial

Open exercises/20/homework/01-product.lua. Using the accumulate pattern, multiply the numbers 1 to 5 together and print the result. (Hint: a product starts at 1, not 0 — anything times zero is zero.)

Problem 2 — Count multiples

Open exercises/20/homework/02-count-multiples.lua. Using the count pattern, print how many numbers from 1 to 50 divide evenly by 7.

Problem 3 — First big square

Open exercises/20/homework/03-first-big.lua. Use the search pattern to find and print the first number whose square is over 200, checking from 1 upward and stopping with break.

Challenge — Range stats in one pass

Open exercises/20/homework/04-stats.lua. In one loop over 1 to 20, work out and print three things: the total (accumulate), how many are even (count), and whether any number is divisible by 9 (flag).

Stuck or finished? Open the homework solutions page.