Regex Question (Regular Expressions: Reuse Patterns Using Capture Groups) BETA

I was able to solve the supplied problem, but I felt like I cheated because I used the a caret and dollar sign at the beginning and end to specify I only wanted 3 or more matches of digits. I believe the solution FCC was looking for was different. Anybody else have different solutions?

I ran into an issue with my code not working if I didn’t implement the caret and dollar sign, but I know there must be a way to solve this without the caret and dollar sign.

Instructions:

Use capture groups in reRegex to match numbers that are repeated only three times in a string, each separated by a space.

Requirements:

Your regex should use the shorthand character class for digits.
Your regex should reuse the capture group twice.
Your regex should have two spaces separating the three numbers.
Your regex should match “42 42 42”.
Your regex should match “100 100 100”.
Your regex should not match “42 42 42 42”.
Your regex should not match “42 42”.
Your regex should not match “101 102 103”.
Your regex should not match “1 2 3”.
Your regex should match “10 10 10”.

My solution:

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

Link to problem:

2 Likes

Try testing with one of the online regEx testers like https://regexr.com/

You didn’t cheat. The specifications are the tests, and their point is to tell you when you are right. Since there’s no one way to accomplish something with code, tests are the only reliable method.

Besides, barring some crazy regex pattern, you wouldn’t be able to accomplish this task since it’s just repeating numbers. And the regex engine is greedy (it will match as often as possible).

In a real world scenario you’d probably just return an array of results and verify the number of matches you want there.

1 Like

Hi, how is the solution above different to this one:

let repeatNum = "42 42 42";
let reRegex = /(^\d{0,})\s\1\s\1$/; // Change this line
let result = reRegex.test(repeatNum);

This one works too.

1 Like

It’s actually not different. It just looks like it.

  • (^\d...)
    • You still anchored the beginning. The parens are just a capture group so that you can reference it later. But there’s nothing before your group so it still anchors to the beginning.
  • \d{0,}
    • the {0,} means to match the preceding token an infinite amount of times
    • since your preceding token is a general match \d, it effectively means the same as \d+
2 Likes

I am not able to understand Reuse pattern using capture group and this solution too. Will someone please help me to understand this solution and this concept?

1 Like

me too ,it took from me a lot of time to comprehend , so first of all as it mentioned in the challenge that the capture group sould be between paranthesses ex: ([0-9]) or (\w) those are groups .
let us use an example :
let repeatStr = “12 12 12”;
let repeatRegex = /(\d+)\s\1\s/; \(\d+) is the first caprture group ,\s is the white space so this group should be followed by white space, \1 is referring to the same group (\d+) because it is the first group
so in the string it is equal 12 so (\d+) =12 and \1 also = 12
let result= repeatRegex.test(repeatStr);
console.log(result); \ retuns true because test method find two 12 followed by\s
and let us add another capture group
let anotherGroup=/(\d+)\s\1\s(\w)\s\2/; \ so here(\w) =\2 because it is the second group
ans lastly if you want to pass the challenge if FCC you have to use the same first pattern with some changes :
let repeatRegex = /^(\d+)\s\1\s\1$/; \ ^= start by this pattern in the string and $ = end by this pattern also , so 42 42 42 42 will not be accepted , I hope this help you

3 Likes

This works

/^(\d+)\s\1\s\1$/

This should probably solve your confusion:

  1. We need to match (42 42 42) but not (42 42 42 42).

Since there we need only 3 repeated pattern here:
The initial regex will look lilke: /(\d+)\s\1\s\1/
But this will match 4 numbers also.

For solving that we can use: ^ and $ at the start and end of regex respectively.

The resulting regex looks like: /(\d+)\s\1\s\1$/

What this says is it will match only a string which matches a string starting from a number and end on 3 numbers separated by space.

Hope this makes sense.

4 Likes

Right, so you do not need two sets of parentheses as the question clearly implies. The wording is misleading. You need one set of parentheses (1 capture group) that gets used 2 times?!

Also, FCC someone, please answer this: the carat and dollar sign? How is this solution so very different to the example given in the question, because that does almost the same but using words instead of numbers.

1 Like

@chris-isnofun I struggled with this too and also tried using 2 groups, even 3 groups 2 with a space and a final group with no space to signify the end of the white space sequence, faffed around with it for ages, then had to resort to the forums, and tbh I still don’t really understand the answer… i get the beginning part:(\d+)\s\1 the group were matching, but then i don’t understand how this translates to check for the group 3 times \s\1$ what if the challenge was different and we wanted to check 4 times, or just two times?

2 Likes

@Pezz18, once you’ve got (\d+), any time you place a \1, that will refer to the original number we matches.

So, let’s take your regular expression as an example, and break it down.

^(\d+)\s\1\s\1$
  • ^ start
  • (\d+) the first number
  • \s a space
  • \1 the next number
  • \s a space
  • \1 the final number
  • $ the end of the string

So we match the original number with (\d+), and then we match it a further two times using \1. In total, that makes us look for three matches of that number, with spaces \s between each of them. Does that clear things up?

29 Likes

@joker314 thanks for this, yes it does, i thought the \1 was to signify the group you had just created was sort of being closed off at this point! not refering back to it!.. i don’t think the challenge information explains this clearly enough!!

your broken down version was great…

thanks

6 Likes

Amen, to that! The example and challenge gap is growing with every challenge.

1 Like

I got you:

let repeatNum = "42 42 42";
let reRegex = /(^|\S)(\d+)\s\2\s\2(\S|$)/; // Change this line
let result = reRegex.test(repeatNum);

The OR operator | can be used to capture if there is a beginning or NOT a white space because the continued pattern would require a white space if it was too many repeats of the number. This way you could have captured it even if there was other non-repeats of the number in the string.

1 Like

As far I can tell, the following regex will pass:

/^(\d+)\s\1\s\1$/

However, that’s only because of the limits of the test statements. The actual question asks for a regex that will match three consecutive numbers (all the same, separated by a space) in a string, but only when it’s three consecutive numbers, not four or five etc. I’m interpreting that correctly right? If so, the regex should be able to pick out the ‘42 42 42’ in the following string:

“Hey, what’s up 42 42 42, we’re going to get pizza”

BUT the regex above (blurred) won’t do that, will it? Because it only matches when the string starts and ends with the repeated number (e.g. “42 42 42”). Thinking about it, what we want is a regex that looks more like:

/(any character that is not the number)(\d+)\s\1\s\1(any character that is not the number)/

So my question is, is there a way to write the negative of the capture group? Because that’s what’s needed to go at the beginning and end, no?

Apologies if none of this makes sense or if I’m missing something obvious, I’m the definition of a noob at all this.

thanks for the break down :pray:

I ran /^(\d+)(\s)\1\2\1$/ through codepen.io. It returned true.

Using that on the challenge and it fails on …
Your regex should reuse the capture group twice.
Your regex should have two spaces separating the three numbers.

Reuse%20patterns

I’m not sure what the difference is between the above and the accepted solution.

I’m enjoying the challenges so far.

write the negative of the capture group

Yeah, this is possible! But not before you’ve defined the capturing group. And that’s the problem. (you’re absolutely right!). This regular expression is impossible to create in JavaScript, and the question’s wording is misleading. I tried to confirm this on Gitter. I was banned from the Gitter chat before receiving a confirmation. :tada: (warning: this is an incredibly one-sided brief perspective of what happened!)

Anyway, you can use something called a negative lookahead if you’ve already defined the capturing group.

(\d)(?!\1)

The above regular expression uses the negative lookahead, it says “assert that \1 does not match here”. The ? means “these brackets do not mean a capturing group”, and the ! means “negative”, i.e. match the opposite. You could use a = instead, to mean “positive”.

So, the above regular expression will match some things yet not others:

+ 51
+ 23
+ 82
+ 76
But it will not match multiples of 11 (i.e., the same digit twice in a row)
- 00
- 11
- 22
- 33
- ..
- 99

But you’re absolutely right – if you try the following, your Regular Expression will not match. The task, as worded, is not giving you inputs in a regular language, and hence it cannot be parsed by a regular expression.

\1(now I capture)

And therefore to attempt a negative lookahead before you’ve defined your capturing group will have the same problem

(?!\1)(\d)

Does not work. :slightly_smiling_face:

Nice catch! Maybe an issue in the non-free GitHub issue tracker would be a good idea, since it would clear it up for folks trying to follow the wording rather than tests.

The relevant repository for the wording of challenges is freeCodeCamp/curriculum.

ahhhh you’re a gem. Thanks so much for this.