Need guidance with regexp(telephone number validator)

I need some hint/link to relevant challenge step or something, because I’m kinda lost how to write correctly block 1 from pseudocode below.
I know how to solve with if…else or looping or something, but I want to solve it with single regexp :upside_down_face:

function telephoneCheck(str) {
  /*pseudocode
  1. start pattern:
  '1' [1]
  or '1 ' [1]\s
  or ''
  IMPLEMENTATION >>> [1]|[1]\s|[] >>> NOPE
  
  2. 2nd block
  3 digits >> \d{3}
  or 3 digits in parenthesis >> \(\d{3}\)
  or 3 digits followed by space >> \d{3}\s
  or 3 digits followed by hyphen >> \d{3}[-]
  or 3 digits in parenthesis followed by space >> \(\d{3}\)\s
  IMPLEMENTATION >>> \d{3}|\(\d{3}\)|\d{3}\s|\d{3}[-]|\(\d{3}\)\s
  
  3. 3rd block
  3 digits
  or 3 digits followed by hyphen
  or 3 digits followed by space
  IMPLEMENTATION >>> \d{3}|\d{3}\s|\d{3}[-]
  
  4. 4thblock/end pattern
  4 digits
  IMPLEMENTATION >>> \d{4}$
  */
  const telephoneRegex = /([1]|[1]\s|[])(\d{3}|\(\d{3}\)|\d{3}\s|\d{3}[-]|\(\d{3}\)\s)(\d{3}|\d{3}\s|\d{3}[-])\d{4}$/
  return telephoneRegex.test(str);
}


const fccTestCases = [
    ["555-555-5555", true],
    ["1 555-555-5555", true],
    ["1 (555) 555-5555", true],
    ["5555555555", true],
    ["555-555-5555", true],
    ["(555)555-5555", true],
    ["1(555)555-5555", true],
    ["555-5555", false],
    ["5555555", false],
    ["1 555)555-5555", false],
    ["1 555 555 5555", true],
    ["1 456 789 4444", true],
    ["123**&!!asdf#", false],
    ["55555555", false],
    ["(6054756961)", false],
    ["2 (757) 622-7382", false],
    ["0 (757) 622-7382", false],
    ["-1 (757) 622-7382", false],
    ["2 757 622-7382", false],
    ["10 (757) 622-7382", false],
    ["27576227382", false],
    ["(275)76227382", false],
    ["2(757)6227382", false],
    ["2(757)622-7382", false],
    ["555)-555-5555", false],
    ["(555-555-5555", false],
    ["(555)5(55?)-5555", false],
    ["55 55-55-555-5", false],
    ["11 555-555-5555", false]
]

for (testcase of fccTestCases) {
    console.log('telephoneCheck(' + testcase[0] + ') expected: ' + testcase[1] + ' result: ' + telephoneCheck(testcase[0]))
}

/*TESTS
Output:

telephoneCheck(555-555-5555) expected: true result: false
telephoneCheck(1 555-555-5555) expected: true result: true
telephoneCheck(1 (555) 555-5555) expected: true result: true
telephoneCheck(5555555555) expected: true result: false
telephoneCheck(555-555-5555) expected: true result: false
telephoneCheck((555)555-5555) expected: true result: false
telephoneCheck(1(555)555-5555) expected: true result: true
telephoneCheck(555-5555) expected: false result: false
telephoneCheck(5555555) expected: false result: false
telephoneCheck(1 555)555-5555) expected: false result: false
telephoneCheck(1 555 555 5555) expected: true result: true
telephoneCheck(1 456 789 4444) expected: true result: true
telephoneCheck(123**&!!asdf#) expected: false result: false
telephoneCheck(55555555) expected: false result: false
telephoneCheck((6054756961)) expected: false result: false
telephoneCheck(2 (757) 622-7382) expected: false result: false
telephoneCheck(0 (757) 622-7382) expected: false result: false
telephoneCheck(-1 (757) 622-7382) expected: false result: true
telephoneCheck(2 757 622-7382) expected: false result: false
telephoneCheck(10 (757) 622-7382) expected: false result: false
telephoneCheck(27576227382) expected: false result: false
telephoneCheck((275)76227382) expected: false result: false
telephoneCheck(2(757)6227382) expected: false result: false
telephoneCheck(2(757)622-7382) expected: false result: false
telephoneCheck(555)-555-5555) expected: false result: false
telephoneCheck((555-555-5555) expected: false result: false
telephoneCheck((555)5(55?)-5555) expected: false result: false
telephoneCheck(55 55-55-555-5) expected: false result: false
telephoneCheck(11 555-555-5555) expected: false result: true
*/

My hint would be that you are probably going to use the pipe in your solution, but you are using it way too often. I think you probably only need to use it once. (Confirmed, I was able to solve it using only one pipe).

Another hint: You might want to review starting at Match All Letters and Numbers.

1 Like

Well, I was able to pass the tests after some minor changes to regexp from original post, thanks for the directions.
I will try to refactor it to use less pipes. Definitely need more practice with regexp.
To clarify: I guess regexp in your solution is also way more concise? :slightly_smiling_face:
And also: to say “or nothing” in regexp I used this:

|.{0}

It was complete improvisation and feels a bit out of place. Do people even write stuff like that in regexps?

Can you explain a little more where you are “saying nothing”? It sounds like maybe you want to say “can be this character (or characters) or nothing”. You might want to check out Check for All or None.

Well, I had this task

So I wrote this part like [1]|[1]\s|.{0}

I was using ? in earlier versions of code, but regexps, which I built with that, were not strict enough: too many test cases were true instead of false. So I freaked out a little and started using pipes like a lot :joy:

This looks like it is for the possibility of having a 1 at the beginning of the phone number. So you have two situations, either the 1 is at the very beginning of the string or it isn’t. How would you check for that? And you don’t need to put the 1 in square brackets. Those are for character classes, which you aren’t using if you are just checking for one number.

This will be simply like:

1?

But the thing is:
if I put it in my whole regex like this:

const telephoneRegex = /1?(\d{3}|\(\d{3}\)|\d{3}\s|\d{3}[-]|\(\d{3}\)\s)(\d{3}|\d{3}\s|\d{3}[-])\d{4}$/

it will fail many tests. It doesn’t fit into logic of all my regexp.

Well, that is just for the very beginning of the regex, you have to do the rest of it. For example, what are the possible characters that come after the 1? You have to take those into account as well.

1 Like

Yeah, I agree. I feel like I need to refresh some knoweledge from regexp section, and refactor whole solution.
After first 1, there can be space or opening bracket.
In my solution, scenario with brackets are placed in the next block of regexp.
Scenario with space in the starting block.

I’ll give you another hint on how to condense the regex. I wouldn’t worry about the parentheses right now. Get it working for all the possible numbers that don’t have parentheses. Then you can go back and address those. One way to think about them is that you either have both of them OR neither of them.

1 Like

So usage of pipe should be related to the parenthesis?
My main problem in the first versions of code was exactly dealing with parenthesis.

How to implement this was the source of confusion specifically.

I think I have enough directions for now. I will try to refactor whole thing and will provide specific questions if they will appear. Great thanks for help!