Let's Count the Smiley Faces From an array

We will be solving a 6kyu problem from CodeWars. This one ->Count the smiley faces! | Codewars

The Question

Given an array (arr) as an argument complete the function countSmileys that should return the total number of smiling faces.

Rules for a smiling face:

  • Each smiley face must contain a valid pair of eyes. Eyes can be marked as : or ;

  • A smiley face can have a nose but it does not have to. Valid characters for a nose are - or ~

  • Every smiling face must have a smiling mouth that should be marked with either ) or D

No additional characters are allowed except for those mentioned.

Valid smiley face examples::) :D ;-D :~)
Invalid smiley faces:;( :> :} :]

Example

countSmileys([':)', ';(', ';}', ':-D']);       // should return 2;
countSmileys([';D', ':-(', ':-)', ';~)']);     // should return 3;
countSmileys([';]', ':[', ';*', ':$', ';-D']); // should return 1;

Note

In case of an empty array return 0. You will not be tested with invalid input (input will always be an array). The order of the face (eyes, nose, mouth) elements will always be the same.

Let's Solve it

We can use Regular Expressions (regex) to quickly and efficiently solve the given problem. To begin, let's import the re library at the beginning of the count_smileys() function. Our next step is to define a regex pattern of all the valid smileys.

The pattern is r"[:;][-~]?[)D]"

Here's a breakdown of the pattern.

[:;] : encasing : and ; with an [] means that we will match the pattern if any one of those two comes up. Since both are valid for the eyes.

[-~]? : Since the nose is optional, we will add a ? mark beside the brackets to signify that the nose is optional and the pattern will match whether the smiley has a nose or not.

[)D] : Finally we will end by writing the mouth.

In the count_smileys function, we will create a variable called count to keep the count of the smileys. We can add a For loop to loop over the items given in the array and use re.search to match the patterns.

Here's the Final result

import re
def count_smileys(arr):
    count = 0
    smileys = r"[:;][-~]?[)D]"
    for item in arr:
        if re.search(smileys, item):
            count += 1
    return count