writing regular expressions
Reading a regular expression is one skill; writing one to capture a pattern you have in mind is the harder, more useful one. It is like translating a sentence from English into a compact formula. The good news is there are reliable habits that turn 'describe all strings that ...' into a correct expression, the same way DFA design has its tricks.
A practical recipe: first state the language in words as precisely as you can ('all strings over {a, b} that contain at least one a'). Then break it into structural parts and translate each. 'Anything before' or 'anything after' becomes (a+b)*. 'At least one a' becomes (a+b)*a(a+b)*. 'Exactly two b's' becomes a*ba*ba*. 'Starts with a' becomes a(a+b)*. Union the alternatives, concatenate the ordered parts, and star the repeatable parts. Then test your expression against a few example strings that should match and a few that should not, this catches most precedence and edge-case errors.
Common patterns are worth memorizing. (a+b)* is 'any string', and ε plus a list is 'these specific strings'. 'Even number of a's over {a}' is (aa)*. 'Does not contain the substring bb' is a*(baa*)*b? in one common form, easier to get right by building a DFA first and converting. The honest limit: many natural-sounding patterns are not regular at all (like 'equal numbers of a's and b's'), so before grinding on an expression, ask whether the language is even regular; if it requires counting unboundedly, no regular expression exists.
Want 'binary strings of even length'? Each step adds two symbols, so the answer is ((0+1)(0+1))*: zero or more blocks of two. Test it: ε (length 0) matches, 01 matches, 011 does not. The block-and-star idea handles 'multiples of k'.
Translate the pattern part by part, then test against examples.
Before writing, check the language is regular at all: anything that needs unbounded counting or matching (like equal a's and b's, or a^n b^n) has no regular expression, no matter how clever you are.