States are memory
A DFA has no variables, no array, no counter — only its current state. So designing one is a puzzle: what is the least I need to remember about the input so far to answer the question at the end? Each possible thing-to-remember becomes one state. If you can get away with a fixed, finite number of them, a DFA can do the job.
Languages a finite automaton can recognise are called regular languages. Today you'll design three of them: an even number of 0s, strings ending in ab, and — the surprising one — binary numbers divisible by 3, using only three states however long the number is.
Remember only what matters
For even-number-of-0s you don't need the count of 0s, only whether it's even or odd: two states. For ends-with-ab you only need to know how much of ab you've just seen: nothing useful, an a, or the full ab. Every new symbol updates that summary. If a b arrives after an a, you've seen ab; any other symbol either starts over or keeps a fresh a.
const ENDS_AB = {
start: "none",
accept: ["ab"],
delta: {
none: { a: "a", b: "none" },
a: { a: "a", b: "ab" },
ab: { a: "a", b: "none" },
},
};Name states after what they remember (even, a, r2), not q0, q1. The design explains itself and bugs show up as names that make no sense.