0

I am stuck on this question on Free Code Camp. I have looked at various explanations in discussion rooms and asked my friends, but I still don't understand it.

Challenge: Use lookaheads in the pwRegex to match passwords that are greater than 5 characters long and have two consecutive digits.

Answer:

 let sampleWord = "astronaut";
 let pwRegex = /(?=\w{5,})(?=\D*\d{2})/;
 let result = pwRegex.test(sampleWord);

I do not understand the reason for having to write \D* to find two consecutive digits. Why doesn't d{2} suffice?

V. Wang
  • 141
  • 5
  • `having to write \D* to find two consecutive digits` that finds any non-digits. `\d{2}` would ONLY match digits. But but digits can be preceded by symbols that are not numeric. – VLAZ Oct 17 '18 at 04:07
  • That answer is wrong anyway. It should be `/^(?=[\s\S]{6})(?=[\s\S]*\d{2})/`. – melpomene Oct 17 '18 at 04:09

1 Answers1

1

The answer is wrong, actually - the regex will fail if there is a single digit, followed by non-digits (or some combination), followed by 2 digits. For example:

const sampleWord = "a1b23";
const pwRegex = /(?=\w{5,})(?=\D*\d{2})/;
console.log(pwRegex.test(sampleWord));

This is because \D matches non-digit characters only - it doesn't match digits, so it won't properly match the inital a2b.

To answer your question, having just \d{2} there instead of repeating characters before it will require that the two digits are at the start of the string (or something else that's wrong):

const re = /(?=\w{5,})(?=\d{2})/;
console.log(re.test('23foo'));
console.log(re.test('foo23'));

Another problem (which might just be a typo or a mis-copied summary) is that "greater than 5 characters long" means "at least 6 characters", so you'd need \w{6}, not \w{5}. (No need for \w{6,}, just matching the first 6 is enough)

To fix it, in the second lookahead, repeat any characters followed by two digits, because you don't know which characters might come before the two-digit substring. Also, best to have the regex fail immediately if the location at the start of the string doesn't match (because if position 0 doesn't match, then no other positions will match either, assuming the string is composed of word characters). So, use ^ to indicate start-of-string anchor:

const re = /^(?=\w{6,})(?=.*\d{2})/;
console.log(re.test('23foob'));
console.log(re.test('foob23'));
console.log(re.test('aa1b23'));
CertainPerformance
  • 260,466
  • 31
  • 181
  • 209