Implement various suggested fixes.

* Use separate regexes to parse short-form and long-form notation.
 * This prevents the error cases of trying to parse 4- and 5-digit codes.
* Use \A and \z to match the beginning and end respectively.
* Prefer twiddled bits to manipulated strings.
 * There's still some string manipulation, but $1 is already a string, so
 * this seems to make a bit more sense than converting it before the math.