Romaji to Kana Converter: React & Next.js — Chapter 2, Exercise 3 ===================================================================== TASK Explain, in your own words, why convertNaiveV1's bug and convertNaiveV2's bug are genuinely different failures -- not just two symptoms of "the tokenizer is broken" -- and why the single longest-to-shortest fix resolves both at once regardless. SOLUTION convertNaiveV1's failure is a real coverage gap: the function literally never attempts a 3-character match at any position in the string, full stop. It doesn't matter what order anything is checked in, because length 3 is simply absent from its own loop. Every word containing a genuine 3-character token -- whether a real yōon combination like "kya" or an ordinary 3-letter gojūon syllable like "shi" or "chi" -- loses at least one character to the raw-fallback path, because the one length that could have matched correctly was never on the table to begin with. convertNaiveV2's failure is a completely different kind of problem: every length IS checked, including length 3, so no coverage is missing. The bug is purely about the *order* those lengths are tried in. Because length 1 is checked before length 2, a standalone 1-character key that happens to also be the correct first character of a longer, correct 2-character key (the syllabic "n" is a real token, and it's also literally the first letter of na/ni/nu/ne/no) wins the match every time, even when the longer token was the one actually intended. Nothing is missing from the search space here -- the search just stops too early because it's willing to accept a shorter, technically-valid match before it ever looks for a longer, more-correct one. So one bug is "the right answer was never even considered," and the other is "the right answer was considered, but a wrong answer got to go first and won by default." That's a real, structural difference, not two flavors of the same complaint. The reason a single fix -- always checking length 3, then 2, then 1 -- closes both is that this ordering satisfies both bugs' requirements at once, for the same underlying reason: it guarantees every length is genuinely attempted (fixing V1's missing-length problem) AND guarantees that whenever more than one valid match exists at a given position, the longest one is always tried, and therefore always wins, before any shorter one gets a chance (fixing V2's wrong-order problem). Longest-to-shortest isn't two separate patches bundled together -- it's the one ordering rule that both "try every length" and "prefer the longest available match" fall out of automatically. WHY THIS WORKS AS AN ANSWER ---------------------------- It correctly separates a coverage bug (a length that's never tried at all) from an ordering bug (every length is tried, but the wrong one is allowed to win), and explains the shared fix as one rule that structurally satisfies both requirements at once, rather than describing it as two coincidentally-compatible patches.