Restrict Possible Usernames - what is wrong?

This one was trickier than I thought, probably because I suck at Regexp. After solving it, I think you will benefit more from just by looking at walkthrough rather than pulling your hair out for couple of hours. So, here we go.

First, I’ll present the working solution that also passes edge cases that FCC doesn’t check.

/^[a-zA-Z]{2,}[\d]*|[a-zA-Z][\d]{2,}$/

This consists of two parts
^[a-zA-Z]{2,}[\d]*$ and ^[a-zA-Z][\d]{2,}$
You might notice this seems totally unrelated to the exercise, but bear with me.

^[a-zA-Z]{2,}[\d]+$
This one checks:
the string beginning with at least two alphabets , ^[a-zA-Z]{2,}
followed by at least one digit towards the end, [\d]+$
So, it matches with things like

"aa"
"aaa"
"a12"
"aa123"
"aaa123"
...

Now the second part, ^[a-zA-Z][\d]{2,}$
This one checks:
the string starts with one alphabet, ^[a-zA-Z]
followed by at least two digits towards the end, [\d]{2,}$
It matches with things like:

"a12"
"a123"
...

If a username matches with either of the condition, it conforms to the given constraints.

  1. The only numbers in the username have to be at the end. There can be zero or more of them at the end.

  2. Username letters can be lowercase and uppercase.

  3. Usernames have to be at least two characters long. A two-letter username can only use alphabet letter characters.

Now, the whole reason I did this is because of the constraint #3, “Two letter username can only use alphabets”

The first two cases are straight forward:
^[a-zA-Z]+[\d]*$
At least one alphabet followed by optional digits. This also conforms to the first half of the constraint #3, minimum length = 2.

But as soon as you add the second half of the constraint #3, things get really messy.
You might think you can just use alternate match with | with [a-zA-Z]{2}
Like ^[a-zA-Z]+[\d]*|[a-zA-Z]{2}$
We just check for the special case where username is length 2, easy right? nope.
This gives false positive for things like "a1", which clearly violates constraint#3.

Now this “a1” becomes the new special case, that we should avoid. The root of problem is our first Regex
^[a-zA-Z]+[\d]*$
One obvious way to avoid our new special case is
^[a-zA-Z]{2,}[\d]*$
Now, "a1" fails, which is good, but we can’t have things like "a12".
Let’s fix that by adding alternative case ^[a-zA-Z][\d]{2,}$
We can concatenate alternative pattern with |

Finally, we arrive at

/^[a-zA-Z]{2,}[\d]*|[a-zA-Z][\d]{2,}$/
2 Likes