Sunday, 24 October 2021

Solve a LeetCode problem with regular expression

Here is the problem LeetCode 2047

Eventually, I figure out a regular express to solve this problem. I will explain how this regular expression works


//Java
import java.util.regex.*;
class Solution {
    public int countValidWords(String sentence) {
        String[] words = sentence.trim().split("\\s+");
        int ans = 0;
        
        Pattern pattern = Pattern.compile("^(([a-z]{0,})|([a-z]+\\-[a-z]+))[!\\.,]?$");
        
        for(String word: words) {
           Matcher matcher = pattern.matcher(word);
            if (matcher.find()) {
                ans++;
            }
        }
        
        return ans;
    }
}

#Python
import re
class Solution:
    def countValidWords(self, sentence: str) -> int:
        arr = sentence.split()
        ans = 0
        for word in arr:
            if re.search("^(([a-z]{0,})|([a-z]+\-[a-z]+))[!\.,]?$", word):
                ans+=1
        return ans

# ruby
# @param {String} sentence
# @return {Integer}
def count_valid_words(sentence)
    words = sentence.split
    ans = 0
    for word in words
        if word.match(/^(([a-z]{0,})|([a-z]+\-[a-z]+))[!\.,]?$/)
            ans = ans +1
        end
    end
    return ans
end

//PHP
class Solution {
    /**
     * @param String $sentence
     * @return Integer
     */
    function countValidWords($sentence) {
        $words = preg_split("/\s+/", trim($sentence));
        $ans = 0;
      
        foreach ($words as $word) {
           if (preg_match("/^(([a-z]{0,})|([a-z]+\-[a-z]+))[!\.,]?$/", $word)) {
                $ans++;
            }
        }
        return $ans;
    }
}

/**
 * Javascript
 * @param {string} sentence
 * @return {number}
 */
var countValidWords = function(sentence) {
    let arr = sentence.trim().split(/\s+/)
    let ans = 0
    arr.forEach((word)=>{
                if (word.match(/^(([a-z]{0,})|([a-z]+\-[a-z]+))[!\.,]?$/)) {
                    
                    ans++
                }
    })
    return ans
    
};

Here is a summary for regular express

How that regulare expression works

  • [!\.,]?$
    one or zero punctuation in the end of word
  • ^(([a-z]{0,})|([a-z]+\-[a-z]+))
    all lower case letters or lower case letters . "-" lower case letters

continue to analyse

^(([a-z]{0,})|([a-z]+\-[a-z]+))
. There are two parts in it

  • ([a-z]{0,})
    string consist of zero or more lower case letters
  • ([a-z]+\-[a-z]+)
    string with hypen which is wrapped with lower case letters

regular expression used here

  • how many time to repreat. ? (0 or once) + (at least once) {0,} (one and more)
  • group (x|y) (x or y). The first part of the expression uses group
  • boundary ^(start) $(end)

If you try to solve it without using regular expression, it will be very tedious.


//PHP
class Solution {

    /**
     * @param String $sentence
     * @return Integer
     */
    function countValidWords($sentence) {
        $words = explode(" ", $sentence);
        $ans = 0;
    
        foreach ($words as $word) {
            $word = trim($word);
            if ($word=="") {
                continue;
            }

            if (self::isValid($word)) {

                $ans++;
            }
        }
        return $ans;
    }
    
    public static function isValid($word) {
        //generate lower case letter array
        $letters = [];
        foreach (range('a', 'z') as $l) {
            $letters[] = $l;
        }
        
        $p = ['!', '.', ','];
            
        $allowedC = array_merge($letters, $p, ['-']);
      
        //count hyphens and index
        $hyC = 0;
        $hi = 0;
        
        //count punctuation and index
        $pc = 0;
        $pi = 0;
        
        for ($i=0; $i1 || $hyC >1) {
            return false;
        }
        
        if ($pc == 1 && $pi != strlen($word)-1) {
            return false;
        }
        
        if ($hyC == 0) {
            return true;
        }
        
        if ($hi-1<0 || $hi+1>= strlen($word)) {
          
            return false;
        }
        
      
        if ((!in_array($word[$hi-1], $letters)) || (!in_array($word[$hi+1], $letters))) {
           
            return false;
        }
        
        return true;
    }
}

No comments:

Post a Comment