Restrict Possible Usernames Exercise

So I ended up getting a correct on this one using my code below but don’t really understand how I got it right since it doesn’t match up with the solution. I know there’s usually more than one way to solve a problem but I feel like what I put is too simple.

Your code so far

let username = "JackOfAllTrades";
let userCheck = /\w\D/g; // Change this line
let result = userCheck.test(username);
console.log(result);

Your browser information:

User Agent is: Mozilla/5.0 (X11; CrOS armv7l 11647.104.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.88 Safari/537.36.

Link to the challenge:
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/regular-expressions/restrict-possible-usernames

It’s really really tricky to devise a proper test for whether your regex is written as intended, so the tests for this challenge will let pass almost any regex that matches the test strings. You’re always free of course to devise a stricter regex, otherwise consider this one a freebie :slight_smile:

1 Like

If one of the test usernames was “1JackOfAllTrades”, your solution wouldn’t have passed. So like chuckadams said, the tests were made in such a way that there are loopholes. This was probably unintended by the authors of the challenge.

Right now, your regular expression evaluates to:

  • any letter or number (\w)
  • any non-number (\D)

When you use this regular expression in .test(), it checks the provided string and returns true or false depending on whether the string contains that particular configuration. In other words, it checks if the string contains any letter or number, and is followed by any non-number.

Taking a look at the correct solution:

let userCheck = /^[a-z]{2,}\d*$/i;

Notice it uses the caret (^) and question mark (?) characters. In a previous challenge, these were introduced as Beginning String and Ending String characters.

The solution under Get a Hint breaks down the regular expression:

/\d*$/

This evaluates to any number (\d), occurring zero or more times (*), occurring only at the end of the string ($).

Next:

/\d*$/i;

This evaluates to the regular expression, but with the flag that accepts uppercase or lowercase (i).

Finally:

/^[a-z]{2,}\d*$/i;

The first half of the regular expression evaluates to the following occurring at the beginning of the string (^), that being any letter ([a-z]), that must appear at minimum two times ({2,}).

I just checked and all of these characters are covered in the Regular Expressions section, so you should be able to reference them again and come to a full understanding of the correct solution.

2 Likes

I figured my answer wasn’t really correct and I just stumbled on a loophole or something. It’s tough keeping all the different combinations straight in my head, thank you for breaking it down for me!

1 Like

This is not technically a solution which satisfies the 3 requirements. A perfectly valid username meeting the requirements would be y75. Your regex expects the first two characters to be letters, but there is no such requirement.

1 Like

You’re right. I overlooked that test case. It seems that the solution provided on the Get a Hint page is incorrect then.

I’m not sure how to write a regular expression to satisfy all possible test cases. To me it suggests using a conditional (usernames have to be at least two characters long, but if so, the characters must be letters).

If the username is only two characters long, then the characters must be letters. That was the challenge intent.

These issues were discussed on GitHub issue 35842. I created a pull request which aims to fix the challenge along with provide a solution which passes all the tests. There is a link to the pull request referenced in the issue.

1 Like

Thanks for the link. I have a question about this, your proposed solution:

/^[a-z]([a-z]|[0-9]{2,}|[a-z]+\d*)$/i

Within the capture group, is the first alternative ([a-z]) redundant? Isn’t the last alternative ([a-z]+\d*) equivalent?