Reuse-patterns-using-capture-groups specify number of patterns

Reuse-patterns-using-capture-groups specify number of patterns
0

#1

Tell us what’s happening:
Okay, I can’t seem to pass the “42 42 42 42” test case that I’m supposed to NOT match. I’ve tried using quantity specifiers, but it either derails other test cases, or it becomes an invalid regex.
What am I missing?
Thanks.

Your code so far



let repeatNum = "42 42 42";
let reRegex = /(\d*)\s\1\s\1/; // Change this line
let result = reRegex.test(repeatNum);

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36.

Link to the challenge:


#2

Okay, so your regular expression will match anywhere in the string. It doesn’t have to match the entire string, and that’s where your problem lies.

If I did

let text = "hi there";
let reRegex = /hi/;
let result = reRegex.test(text);

Then it would match. This is because /hi/ matches the hi at the start of hi there, even though it doesn’t match the entire string. Same goes for your regular expression. It’s really close, but it will match the first three 42s, and stop there without making sure that there aren’t anymore.

To tell the regular expression that it must stop right there, you can put a $ sign. This is code for “the end of the string”. There’s an equivalent symbol for the start of a string, which is ^. (You also don’t want to match 52 42 42 42, so this will be needed too!)

Here’s are some examples of using $, and using ^ acts in the same way (remember to put it at the start instead, though).

let text, reRegex, result;

text = "hi there";
reRegex = /hi/;
result = reRegex.test(text); // true

text = "hi there";
reRegex = /hi$/;
result = reRegex.test(text); // false

 text = "wuddup hi";
 reRegex = /hi$/;
 result = reRegex.test(text); // true

Don’t forget, you’ll need to make sure that it starts at the start and ends at the end, so you’ll need to use both the ^ and the $. The ^ goes at the start (because it wouldn’t make sense to have the start of the string after matching a bunch of stuff already – for that would mean the string starts in the middle!); and the $ goes at the end (for similar reasons).

For example, the regular expression /^hi$/ will only match hi. It won’t match wuddup hi, nor will it match hi there


#3

Ah! Thank you! This was very helpful!!


#4

Though not an actual test case used by the FCC challenge, based on the challenge requirements, the following should return true, but using the ^ and $ around the existing regular expression would cause it to return false.

let repeatNum = "52 42 42 42";

Again, the test cases are very simple and do not test the above edge case, but thought I would share in case you wanted to develop a more robust regular expression.


#5

Oh oops! Thank you for your response… but I’ve spent a little white trying to create a Regular Expression simply to verify that there are exactly three occurrences of (\b\d+\b), but I can’t seem to find a way. You can’t reference capturing groups before they’ve been defined, so if there are four space-separated numbers, it’ll elect to omit the first one in the match. I don’t see how to force it to start a match there. Lookbehinds would also have to reference the capturing group before it’s been defined, as far as I can tell.

Do you have a solution yourself for this challenge which matches that test case, and if so, could you place it in spoiler tags – because I’m genuinely interested.

Is it possible that a Regular Expression simply cannot check that there are exactly three occurrences of \b\d+\b? If so, perhaps the challenge should be reworded?


#6

I followed your solution and it almost worked.
It matched every test case except
"Your regex should have two spaces separating the three numbers."

Could you help ?


#7

Please show us your code, so we can help you.

To enter a code block into the forum, precede it with a line of three backticks and follow it with a line of three backticks to make easier to read. See this post to find the backtick on your keyboard. The “preformatted text” tool in the editor (</>) will also add backticks around text.

Also, please don’t cross-post the same question across multiple topics. Limit the same question to a single topic. That way, people don’t waste their time providing you an answer in one thread when you have already accepted an answer in a different thread.


#8

I used this
/^(\d+)(\s)\1\2\d+$/


#9

Kay, that’s a wonderful Regular Expression you’ve produced. It should pass all the tests, but you’re trick of placing a space character into a capturing group and then referencing stuff, freeCodeCamp doesn’t realise that you’ve actually used two spaces. However, note that you don’t actually need to make sure that the separators are both the same type of whitespace, just that they both are whitespace – so you could just do /^(\d+)\s\1\s\d+$/. That should pass all the tests.

But be warned, your Regular Expression isn’t correct. It’ll pass the tests, but your final \d+ should instead still be a reference to your capturing group (\1). For example, with your regular expression, 42 42 52 would pass; but instead it should fail. Good luck!


#10

Sorry for the late reply. I have played around with a regular expression that would make the “52 42 42 42” return true, but so far I have not figured it out. I will think about it a bit more and hopefully post a solution soon.


#11

I think it’s not possible, because RegExps can only match regular languages. I also asked some of my friends, they couldn’t figure it out. I asked in the fCC gitter room, and nobody figured it out within a few hours.

The reason why this isn’t possible is that you can’t refer to a capturing group before something has been captured. That means you can’t say {not a \1}(\d+)\s\1\s\1.


#13

I tried some combinations after posting here. Like /^(\d+) \1 \1$/.
But didn’t work either.
The one you said here worked just fine.
Thank you very much.


#14

Try this, if you’re stuck

let repeatNum = “42 42 42”;
let reRegex =/^(\d+)\s\1\s\1$/; // Change this line
let result = reRegex.test(repeatNum);


#15

I’ve been trying to figure out the solution to this challenge using Regexr, and this code doesn’t capture anything. I’ve tried it in regex101 and it doesn’t work either. I’m so confused as to why it does work in this challenge… I don’t think I’ve learned anything about how to properly use Regex in the end, I just don’t get it.

But thanks for your code, because I was getting increasingly frustrated by being stuck on not passing ‘42 42 42 42’…


#16

Hey, don’t feel too bad - those lessons are pretty unclear unfortunately, I found they actually made me more confused about what was going on then when I started in places.

The code above does seem to work for me in regex101, what does it show on your screen?

PS.
http://www.rexegg.com has a very good tutorial and reference materials. It might be a bit overwhelming at first though.


#17

You’re welcome :slight_smile:


#18

Passed the test but I still don’t understand what are capture groups.

What is a group? And why we need to put /1 after the search pattern?


#20

The capture group just specifies a section of your regular expression that you want to reuse. So instead of a regular expression re = /\d+\s\d+\s\d+/ (which is not quite the solution), you can reuse parts that are repeated with the \1, i.e. re = /(\d+)\s\1\s\1/ where the \1 references the first capturing group (stuff in parenthesis) and gets re-used like a variable.

If you had two different capturing groups in the same regular expression, you would use \1 for the first group and \2 for the second. It’s because an array is created (not starting at zero) behind the scenes.


#21

So what is the difference between the first group and the second group? Is that they are created in different arrays?


#22

i solved it with this - let reRegex = /^(\d{1,})\s\1\s\1$/; but honestly I don’t understand why it worked. I had stuck with this for hours and finally this solution worked… I wish somebody could explain why it worked