Counting principles: multiply the and-thens, add the eithers
All counting stands on two laws: independent sequential choices multiply (4 shirts × 3 pants = 12 outfits), disjoint cases add (3 pastas + 4 pizzas = 7 dinners). Factorials, permutations, combinations and the size of your CI matrix are these two rules applied over and over.
A reviewer once asked an innocent question about a CI config: the matrix listed 3 browsers, 4 operating systems, and 2 locales — so how many jobs is that per push? Half the room said 9, adding the numbers up. The pipeline ran 24. Then mobile Safari joined the browser list and the count quietly became 32; a third locale pushed it to 48; a node: [18, 20] axis doubled everything again to 96. Nobody ever decided to burn an hour of compute per commit — the matrix multiplied while everyone was merely adding one small thing at a time. The gap between the guessed 9 and the real 24 is not a CI quirk; it is the gap between the two laws that govern all counting. Knowing which law applies — and spotting the moment neither does — is a skill you will reuse on test matrices, password policies, nested loops, and feature-flag explosions for the rest of your career.
- State the multiplication rule and the addition rule, and identify which applies to a given problem
- Compute the size of a CI matrix, password space, or nested loop with the product rule
- Apply the addition rule with the inclusion–exclusion correction for overlapping cases
- Build permutation and combination counts from the two rules alone, without memorizing formulas
And-then choices multiply
You own 4 shirts and 3 pairs of pants. How many outfits? Picture the choice tree: from the root grow 4 branches, one per shirt; from each of those grow 3 branches, one per pair of pants. Count the leaves: 4 groups of 3, so 12. That is the multiplication rule (the rule of product): when a task splits into sequential stages — make this choice, and then that one — and the number of options at each stage does not depend on what was chosen earlier, the total is the product of the per-stage counts.
The fine print earns its keep: the options themselves may change with earlier choices — only their count must not. Choosing 2 distinct letters for a code gives 26 options for the first, then 25 for the second (whatever you picked is gone; the leftovers differ each time, but there are always 25 of them) — 26 · 25 = 650 ordered pairs. The rule still applies, because every branch of the tree fans out into the same number of sub-branches.
When you see a nested loop, ask yourself: is each level an independent “and then”? If so, you can multiply the per-level counts instead of running the code:
const browsers = ["chrome", "firefox", "safari"]; // 3 options
const oses = ["ubuntu", "macos", "windows", "alpine"]; // 4 options
const locales = ["en", "ru"]; // 2 options
let jobs = 0;
for (const b of browsers) // pick a browser, AND THEN…
for (const o of oses) // …pick an OS, AND THEN…
for (const l of locales) // …pick a locale
jobs++;
console.log(jobs); // 3 · 4 · 2 = 24 — one job per leaf of the treePassword space as multiplication
The same rule prices a password space. An 8-character lowercase password is 8 sequential choices from 26 letters: 26^8, about 2.1 × 10¹¹ strings. Widen the alphabet to 62 symbols (upper, lower, digits) and stretch to 12 characters: 62^12, about 3.2 × 10²¹ — ten billion times more. Each added position multiplies the whole space by the alphabet size again, which is why password length beats clever character substitutions: length adds factors, substitutions only fatten one factor slightly.
▸Why this works
Why does the rule insist on independence of counts? Because one dependent stage breaks the clean product. A real CI matrix usually carries exclude: entries — say, safari on alpine is excluded. Now the OS stage offers 4 options for two of the browsers but only 3 for the third: the choice tree is lopsided, and no single product describes it. You size it as the full product minus the excluded leaves: 3 · 4 · 2 − 1 · 1 · 2 = 22 jobs. Multiply first, then subtract the dead branches — that is how every real matrix with exclusions is counted, and forgetting the correction is how CI bills surprise teams in both directions.
Either-or cases add — and the overlap tax
Dinner is one dish. The menu has 3 pastas and 4 pizzas. You are not choosing a pasta and then a pizza — you choose one dish from two disjoint cases (no dish is both a pasta and a pizza), so the counts add: 3 + 4 = 7 possible dinners. That is the addition rule (the rule of sum): when the outcomes split into cases with no element in common, the total is the sum of the case counts.
The load-bearing word is disjoint. Count files that are large or recently modified: 80 large plus 50 recent is not 130 when 20 files are both — those 20 were counted twice, once in each case. Subtract the double count once: 80 + 50 − 20 = 110. You met this correction in unit 03 as inclusion–exclusion on sets: the size of a union is the sum of the sizes minus the size of the intersection. The addition rule is simply the happy special case where the intersection is empty.
Real problems chain both rules. A meal deal is one dish and then one of 2 drinks: the dish count comes from addition over disjoint cases (3 + 4 = 7), and the drink is an independent next stage, so the deals multiply: 7 · 2 = 14.
A menu offers 3 pastas and 4 pizzas; a meal deal is one dish plus one of 2 drinks. How many distinct meal deals exist?
Permutations built from the product rule
How many ways can n distinct items stand in a line? Apply the multiplication rule n times: n choices for the first slot, and then n − 1 for the second (one item is used up), and then n − 2, down to 1. The product n · (n−1) · … · 1 is written n! and pronounced “n factorial”. Five services to deploy in sequence: 5! = 120 possible orders — which is why “just try every deploy order” stops being a plan around n = 5.
Stop the product early and you get ordered selections: a podium (gold, silver, bronze) chosen from 10 runners is 10 · 9 · 8 = 720 — three stages, then stop. This is the permutation count of 3 out of 10, and order genuinely matters: gold-Ann-silver-Bo is a different podium from gold-Bo-silver-Ann.
Combinations: divide out the orderings
Now the one genuinely new move. Choose an unordered team of 3 from 10 people. The 720 ordered selections overcount it: the team of Ann, Bo and Cy appears once for every way to order those three people — and orderings of 3 items number 3! = 6. Every team is counted exactly 6 times, no exceptions, so the number of teams is 720 / 6 = 120. That division argument — group the ordered selections by which set they contain, observe that every group has exactly k! members, divide — is the entire theory of combinations. C(n, k) is not a formula to memorize; it is “count ordered with the product rule, then divide out the orderings you never cared about.”
The misconception this lesson dismantles: order always matters, so the bigger permutation number is the safe default. A lottery draw of 6 numbers from 49 is a set — the machine’s draw order is noise nobody records. Count it with permutations and you get about 10 billion; the real ticket space is that divided by 6! = 720, which is 13,983,816. Mix the two up and your odds are off by three orders of magnitude. Ask whether two selections that differ only in order count as the same outcome here. Podium: no — keep the product. Lottery ticket, on-call team, hand of cards: yes — divide by k!.
Problem: You have 5 microservices to deploy in a specific sequence during a maintenance window. How many different deployment orderings exist?
Step 1 — Identify the structure. Each deployment slot is a distinct sequential stage: pick the first service to deploy, and then the second, and then the third, and then the fourth, and then the fifth. Every choice removes one option from the remaining pool.
Step 2 — Count stage by stage. First slot: 5 choices. Second slot: 4 remain. Third: 3. Fourth: 2. Fifth: 1 (no choice left).
Step 3 — Apply the product rule. The stages are sequential and the count at each stage is independent of which specific services were chosen earlier (it only depends on how many are left — always one fewer). So multiply: 5 · 4 · 3 · 2 · 1 = 120.
Step 4 — Interpret. 5! = 120 distinct deployment orders. This is why “just test every order in staging” is impractical even for 5 services — and becomes completely infeasible at 10 services (10! = 3,628,800).
Sanity check: Does order matter here? Yes — deploying the auth service before the API service is a different operational choice from deploying API before auth. So we keep the full permutation count and do not divide by anything.
From 10 engineers you pick an unordered on-call trio. Which count is right, and why?
Counting runs on two laws. The multiplication rule covers and-then structure: a task built from sequential stages, where the number of options per stage does not depend on earlier picks, has as many outcomes as the product of the stage counts — 4 shirts and 3 pants make 12 outfits, three nested loops run 3 · 4 · 2 times, an 8-character lowercase password lives in a space of 26^8. The addition rule covers either-or structure: one choice split into disjoint cases has as many outcomes as the sum of the case counts — 3 pastas plus 4 pizzas is 7 dinners — and when the cases overlap, the intersection was counted twice and gets subtracted once, which is inclusion–exclusion. Everything classical is these laws repeated: n! orders n items by multiplying n shrinking stages; the permutation count of k from n stops the product after k factors (10 · 9 · 8 = 720 podiums); and combinations divide that by k!, because an unordered team was counted once per ordering of its members — exactly k! times each, so 720 / 6 = 120 teams. The misconception to retire: order does not always matter — a lottery ticket is a set, and counting it as ordered inflates the space 720-fold. Ask instead whether two selections differing only in order are the same outcome here; multiply while they are not, divide by k! the moment they are. Now when you see a CI matrix expand unexpectedly, or a password policy review — you know which law just fired and exactly how to count it.
Practice
Start at the top. Tasks go easiest → hardest: recall a fact, apply it to a case, then a senior-level stretch. Open one, attempt it, then reveal.
Something unclear?
Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.