String manipulation + Regex

I’ve been working on this Coderbyte Algorithm problem to practice Regexp in Javascript and can’t figure out why my solution doesn’t work. Can someone help me debug?

Have the function SimpleSymbols( str ) take the str parameter being passed and determine if it is an acceptable sequence by either returning the string true or false . The str parameter will be composed of + and = symbols with several letters between them ( ie. ++d+===+c++==a) and for the string to be true each letter must be surrounded by a + symbol. So the string to the left would be false. The string will not be empty and will have at least one letter.
Your code so far


function SimpleSymbols(str) { 
    str = "=" + str + "="
    for (let i = 0 ; i < str.length; i++){
        if (str.match(/\w/i) !== null){
            if (str[i-1] === '+' && str[i+1] === '+'){
                return true
            }
        }
        
    }
  // code goes here  
  return false; 
}

Your browser information:

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

Link to the challenge:
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/regular-expressions/remove-whitespace-from-start-and-end

There is no easy fix for our code, it’s quite far from solution. As you said you need to check 2 conditions:

  1. str only contains set of following characters: [a-z+=];
  2. all letters [a-z] has to be surrounded by +;

Even if you fix typo in your for loop and do str[i].match(/\w/i), that will check only the first character, isn’t it?

You need a regex testing following: a group consisting of 3 subgroups:

  1. Zero to any [+=]
  2. One +[a-z]+
  3. Zero to any [+=]
    And this group has 1 or more occurrences from start to the end of the str

Let me know if that helped :slight_smile:

so I ended up solving the challenge like this:

    //  find letter character 
    for (let i = 0; i < str.length; i++){
        if (/[a-z]/i.test(str[i])){
            if (str[i-1] !== '+' || str[i+1] !== '+'){
                return false
            }
        }
        
    }

  return true; 
         
}

I’m a bit confused as to what would happen if I were to run the code with str = “+d+=3=+s+”.

The 1st character in the string ‘+’ would fail the first If-Condition since it is not a character from ‘a-z’ and therefore exit the loop and return true, correct? Now would the loop continue and move on to the next character ‘d’ or would the loop end since it returned true for ‘+’?

I tried another variation to my solution to test my understanding and I don’t understand why this variation below doesn’t work for all test-cases?

function SimpleSymbols(str) { 
    for (let i = 0; i < str.length; i++){
        if (str[i].match(/[a-z]/i)){
            if (str[i-1] === '+' && str[i+1] === '+'){
                return true 
            }
        }
    }
      return false; 
}

For the input “f++d+” I would expect it to return false yet it returns true. Please help me find the holes in my logic :

  1. The function will loop thru the string “f++d+” to find each character that passes the first if-condition: ‘f’, and ‘d’. How come the loop doesn’t return when it reaches the first ‘+’ in the string? I would assume that since ‘+’ does not pass the first condition of the function it would fail and then exit the loop and return false. How come it seems to move on until it finds the next character that passes the test: ‘d’?

  2. Once the function pulls out the 2 characters (‘f’, and ‘d’) in the string that pass the first if-condition, it will then run it thru the next if-condition seeing if ‘+’ is on the left and right of ‘f’ and ‘d’. I would assume that since there is no ‘+’ to the left of the ‘f’, the condition would fail and return false, yet this is not the case.

How about a re-think? Use lookbehinds and lookaheads – get an array of characters surrounded by plus signs, and a second array of characters. If the two don’t return the same number of elements, its falsy. Otherwise, it’s truthy.

function simpleSymbols(str){
  // First regex uses lookbehind and lookahead, only returns if 
  // the char is preceded and followed by a plus.
  let myFullRegex = /(?<=\+)[a-zA-Z](?=\+)/g;
  // Second regex returns each character
  let myCharRegex = /[a-zA-Z]/g;

  // Get an array of all matches for BOTH
  let matches = str.match(myFullRegex);
  let chars = myString.match(myCharRegex);

  // if both match, we return true. If not, then it's an invalid string. False.
  return matches.length == chars.length;
}


1 Like

thanks! I haven’t really used lookbehinds and lookaheads yet so I was trying to solve the challenge without it. I understand your solution but could still using some clarification on my other questions from my post. Trying to get a better grasp on how if-statements work within the context of a for-loop.

The reason is your logic is exactly backward. You’re saying “try every character, and if it’s an a to zed, check if it is preceded and followed by a plus. If it is, return true.”

Which sounds right, but is backwards. You’re saying, if ANYWHERE in the string, you find +[a-z]+, return true. A single one of these, and the whole string is truthy.

Instead, make the logic go like this: “For each character, if it is NOT preceded by and followed by a plus, return false. If every character has been tested, and we haven’t returned, then return true.”

As has been said in another one of your posts, you may benefit from going through some of the freecodecamp lessons – not only are they actual coding practice, but it’s also looking at the logic.

1 Like

thanks for the clarification.

If I add an else-statement to my function to return false it seems to work as well. It seems like adding the else-statement makes the if-statement more strict (ALL characters a-z in the string must have a ‘+’ before and after it, otherwise return false), whereas the if-statement without an else only requires at least 1 instance of the required condition to be truthy.

function SimpleSymbols(str) { 
    for (let i = 0; i < str.length; i++){
        if (str[i].match(/[a-z]/i)){
            if (str[i-1] === '+' && str[i+1] === '+'){
                return true 
            } else {
                return false
            }
        }
    }
}

So now, the first character alone will be the only one checked. If it has plus signs, it will return true. If not, it will return false.

Strict, and probably not what you want.