Worked examples — Reducibility — many-one reductions
The scenario matrix
Every many-one reduction problem is really one of these cells. Below, each worked example is tagged with the cell it covers, so by the end every row is filled.
| # | Cell (the case class) | What makes it tricky | Covered by |
|---|---|---|---|
| C1 | Both directions checked (YES→YES and NO→NO) | forgetting the NO direction | Ex 1 |
| C2 | Decidability transfer ( decidable ⇒ decidable) | using + a decider correctly | Ex 2 |
| C3 | Undecidability transfer ( undecidable ⇒ undecidable) | picking the right known-hard | Ex 3 |
| C4 | Degenerate targets: (everything) or (nothing) | when does a reduction even exist? | Ex 4 |
| C5 | Complement flip () | same , sets swapped | Ex 5 |
| C6 | Wrong-direction trap | reducing new→known proves nothing | Ex 6 |
| C7 | Recognizability (not decidability) transfer | where target-decider may loop | Ex 7 |
| C8 | Real-world word problem | translating an informal task into | Ex 8 |
| C9 | Exam twist: build that is total even when it looks like it must simulate | avoid running inside | Ex 9 |
Example 1 — both directions, a concrete finite reduction (C1)
Step 1. Define Why this step? We do not need to preserve at all — a many-one reduction only needs the YES/NO bit to survive. So we throw the input away and output a hand-picked string whose membership in matches membership in . The string has odd length (in ); the string has even length (not in ).
Step 2. Check the YES direction. If starts with then , and is odd, so . ✓ Why this step? This is — the "useful" half.
Step 3. Check the NO direction. If does not start with (starts with , or is empty) then , and is even, so . ✓ Why this step? This is the half everyone forgets. Without it a NO instance could sneak in as a YES image and the translator would lie — the reduction would wrongly accept a string not in .
Step 4. Conclude is total and computable: read the first symbol, output or . Always halts. Hence . Why this step? is only earned once we confirm is a computable total function — the definition demands halting on every input, so we must explicitly certify termination before claiming the reduction exists.
Verify (explicit case table):
| starts with 1? () | odd? () | agree? | ||
|---|---|---|---|---|
| yes | yes | ✓ | ||
| no | no | ✓ | ||
| no | no | ✓ | ||
| yes | yes | ✓ | ||
| no | no | ✓ |
All rows: column matches column. ✓
Example 2 — decidability transfer, used as a sanity check (C2)
Forecast: is trivially decidable ("does the string contain a 1?"). Will correctly turn "more 0s than 1s" into "contains a 1"?
Step 1. Compute by one scan. Why this step? Counting is a guaranteed-terminating mechanical operation, so stays total — a looping would destroy decidability transfer, so we must keep every step of terminating.
Step 2. If output ; else output . Why this step? We want the presence of a 1 in the output to track " says YES". When we append a ; when we output the single symbol (no anywhere).
Step 3. Both directions:
- () contains a . ✓
- () contains no . ✓
Step 4. Apply Theorem 1 (decidability transfer): decidable, , so decide by "compute , then check if it contains a ." Since is obviously decidable directly, this is a sanity check that the machinery is sound. Why this step? This is the payoff of the whole reduction: Theorem 1 lets us reuse 's decider through , so establishing was the point — the conclusion is not automatic until we invoke the transfer theorem by name. See also Turing-recognizable vs Decidable languages.
Verify (explicit case table):
| more 0s? () | has a 1? () | agree? | |||
|---|---|---|---|---|---|
| yes | yes | ✓ | |||
| no | no | ✓ | |||
| no | no | ✓ | |||
| yes | yes | ✓ | |||
| no | no | ✓ |
All rows agree. ✓
Example 3 — undecidability transfer (C3): the direction that does real work

Figure — what you are looking at. The board shows the machine that the reduction writes down, split into its only two possible fates. Top box (chalk-blue): the case accepts . Because erases its own input and just runs on , once accepts the machine accepts no matter what was — so it "leaks" acceptance to every input and , which is non-empty. The blue arrow (labelled ) carries this to the right column: . Bottom box (chalk-pink): the case does not accept . Then the inner simulation never accepts, so accepts nothing, , and the pink arrow carries it to . The single design — "ignore , run on " — is exactly what makes 's language all-or-nothing: it is either every string or no string, and which of the two it is exactly mirrors whether accepts . That all-or-nothing property is the whole trick.
Step 1. Given , build the description of a new machine : "On any input : erase , run on ; if accepts , accept." Why this step? 's behaviour no longer depends on (top vs bottom box in the figure). So its language is either all strings (if accepts ) or empty (if does not) — never anything in between.
Step 2. Set . Why this step? only writes down the code of ; it never runs . Pure text editing ⇒ is total and computable (running inside could loop and would make partial — see Ex 9).
Step 3. Check the biconditional against (the " does not accept " language; recall means exactly ):
- ( does not accept ) . ✓ (pink path)
- ( accepts ) . ✓ (blue path)
Step 4. Apply Theorem 2 (undecidability transfer): so , and since is undecidable (complement of an undecidable language is undecidable), is undecidable. Hardness flowed along the arrow into . Why this step? Theorem 2 (contrapositive of decidability transfer) is what actually concludes the proof: a valid from a known-hard language forces the target hard. Without naming this theorem, Steps 1–3 are just a function — the undecidability result is only earned here.
Recall Why reduce
and not ? Because our maps "accepts" to "non-empty" — the YES side of lands on the NO side of . Flipping to realigns YES with YES. (You could equally state it as .) Compare Rice's Theorem, which gives this for free.
Verify (explicit two-world table):
| world | ? | ? | agree? | |
|---|---|---|---|---|
| accepts | no | no | ✓ | |
| does not accept | yes | yes | ✓ |
Both worlds: source membership matches target membership. ✓
Example 4 — degenerate targets and (C4)
Step 1. Take . We need with . But is always true. So the biconditional forces to always be true, i.e. . Why this step? The right side of the biconditional is a constant; a biconditional with a constant right side forces the left side constant too.
Step 2. So holds iff . Symmetrically holds iff (since is always false, forcing ). Why this step? We must cover the nothing language too — the same constant-side argument runs with "false" instead of "true", so both degenerate targets are pinned down.
Step 3. The other direction: what reduces from a trivial ? If , pick any fixed and set (constant). Then (always) (true) — valid provided . If there's no such , so , matching Step 2. Why this step? Constant functions are the simplest totals; checking when they work isolates the only obstruction (an empty target has no image to hit).
Step 4. The four trivial-target cases, spelled out:
| does exist? | reason | ||
|---|---|---|---|
| yes | any fixed member of | ||
| no | has a YES string but has no member to send it to | ||
| yes | any fixed non-member... none exist, but every so map anywhere; biconditional is "false true"? no — see note | ||
| yes | any fixed non-member of (every string) |
Careful reading of row 3: means every is a NO instance, so we need for all — impossible, since everything is in . So . Corrected: reduces only to targets that miss at least... in fact iff (we need a non-member to hit). The clean rule is below.
Verify (explicit truth check): treat each language as a pair (has-a-member?, has-a-nonmember?). , . Then needs to have a member; needs to have a non-member. Checked below.
Example 5 — the complement flip (C5)
Step 1. Recall . Negate both sides: , i.e. (using the complement definition ) . Why this step? A biconditional is logically identical to . No new function needed — the same translator works on the complemented sets.
Step 2. Verify concretely. (doesn't start with 1); , even, so . ✓ And ; , odd, . ✓ Why this step? A single algebraic negation can hide a slip; plugging in a YES and a NO instance confirms the complemented reduction really holds.
Step 3. Why we care: this is the engine for non-recognizability proofs. If and is not Turing-recognizable, then neither is (Theorem 4); complementing lets you carry results about around (see Turing-recognizable vs Decidable languages and Closure properties of language classes).
Verify (explicit case table, same , complemented sets):
| ? (not start 1) | ? ( even) | agree? | ||
|---|---|---|---|---|
| yes | yes | ✓ | ||
| no | no | ✓ | ||
| yes | yes | ✓ | ||
| no | no | ✓ |
All rows agree. ✓
Example 6 — the wrong-direction trap (C6)
Step 1. State the transfer theorem precisely: Theorem 2 says and undecidable undecidable. The hardness lands on the right end of . Why this step? We must pin down which side inherits hardness before judging the argument.
Step 2. The student's reduction is . Matching this to Theorem 2, the "" is and the "" is . Theorem 2 would let us conclude something about the right side () — which we already knew is undecidable. It says nothing about the left side . Why this step? "Hardness flows along the arrow" — into the head, not the tail; matching the roles to the theorem exposes that the wanted conclusion is about the tail, which the theorem never constrains.
Step 3. The correct argument reverses the arrow: (the parent's Example 1: build that runs on , accepts if accepts and loops if rejects). Now, matching Theorem 2, "" = the known-hard and "" = the target , so undecidability flows into . Conclusion earned. ✓ Why this step? Fixing the direction re-aligns the known-hard language with the tail and the target with the head, which is the only configuration Theorem 2 lets us conclude from.
Verify (logic check): the inference " and undecidable undecidable" is valid; the inference " and undecidable undecidable" is not valid (a decidable can reduce to an undecidable ). Checked below.
Example 7 — recognizability, not decidability, transfer (C7)
Step 1. Let recognize : it accepts every , but on it may reject or loop forever (this is the definition of recognizer given at the top). Why this step? "Recognizable" is the weaker guarantee — halting only promised on YES instances, so we must track where looping can occur.
Step 2. Build : on input , compute (halts, total), then run on ; accept if accepts. Why this step? total ⇒ the first stage always finishes; the loop risk lives only inside , so we have located the single source of non-halting.
Step 3. Correctness: accepts accepts . So accepts exactly the strings of . Why this step? This chain is the reduction property threaded through the recognizer; it certifies that the set accepts is precisely , which is what "recognizes " means.
Step 4. But when , we have , and may loop — so may loop on those inputs. It never wrongly accepts, but it need not halt-and-reject. That is exactly a recognizer, not a decider. This is Theorem 3. Why this step? It explains the gap: the halting guarantee we lost in we cannot recover in , so decidability transfer downgrades to recognizability transfer.
Step 5. Contrapositive (Theorem 4): if is not recognizable, then is not recognizable — the standard tool for the " is not recognizable" family. Why this step? Flipping Theorem 3 gives the workhorse used to prove languages outside the recognizable class; it is the recognizability twin of Example 3's undecidability transfer. Connects to Decidability and the Halting Problem.
Verify (acceptance identity): on YES instances the accept-condition chain is a logical identity; it never accepts a NO instance. Checked below.
Example 8 — a real-world word problem (C8)
Step 1. Represent each config as a Turing machine that, on any input, simulates the config's rule engine and emits the name of a triggered step whenever the config would fire one. Why this step? We translate the informal predicate "triggers a step" into the formal "produces output," aligning with so a can even be stated.
Step 2. Set . This is text editing over the config, so is total and computable. Why this step? We never run the config inside (that could loop); we only compile it — same discipline as Example 3 and 9, which keeps total as demands.
Step 3. Both directions:
- (no step ever triggers) never outputs . ✓
- (some step can trigger) can output . ✓ Why this step? Both directions confirm the YES/NO bit survives, so the translation is a genuine reduction and not a one-sided illusion.
Step 4. Apply Theorem 2 (undecidability transfer): and symmetrically, so the two are equivalent; since the underlying emptiness question is undecidable (Example 3's ), no perfect linter exists. Why this step? The practical verdict ("no decider possible") is only licensed by Theorem 2 applied to the equivalence with — the reduction is the bridge, the transfer theorem is the conclusion. The engineering takeaway: ship a sound over-approximation (a recognizer), never claim a decider.
Verify (explicit two-world table):
| world | triggers a step? | ? | outputs? | ? | agree? |
|---|---|---|---|---|---|
| never triggers | no | yes | no | yes | ✓ |
| can trigger | yes | no | yes | no | ✓ |
Both worlds: matches . ✓
Example 9 — the exam twist: keep total (C9)
Step 1. Consider the case loops on (neither accepts nor rejects). Then 's "run on " step never halts, so is undefined. Why this step? with looping is a genuine NO instance of we are obligated to map somewhere. If diverges there, is partial, not total — illegal.
Step 2. So the proposed is not a valid reduction. The fix is to build by editing 's description (as in Ex 3 and Ex 8): output the code of a machine that will do the simulation later, so itself always halts. Why this step? Delaying the simulation to run-time of the output machine keeps total while preserving the YES/NO correspondence — the definition of is only met by a total .
Step 3. General rule of thumb for exams: may compile but must not execute the machine it is reasoning about. Compilation halts; execution may not.
Recall One-line diagnosis test
Ask: "On the hardest NO instance — a looping — does my still halt?" If not, is partial and the reduction is invalid.
Verify (logic check): "run then branch" is total halts on all inputs, which is not guaranteed for ; the code-editing version is unconditionally total. Checked below.
Scenario matrix — filled
Recall Did we cover every cell?
Which example handles the " / " degenerate case? ::: Example 4. Which example is the one where hardness must flow into the target? ::: Examples 3 and 6. Which example shows a recognizer arises when the target-decider may loop? ::: Example 7. Which example fails only because becomes partial on a looping machine? ::: Example 9. Which example uses the same on complemented sets? ::: Example 5. Which example translates an informal engineering task into a reduction? ::: Example 8.
Related: Polynomial-time reductions and NP-completeness adds a time bound to the exact same -discipline you drilled here.