Interview Questions in Python – Regular Expressions

Comments

Interview Questions in Python – Regular Expressions

Welcome to the first article in a series of interview questions and solutions in python! I will be walking through the solutions in detail, so you understand exactly what is going on. The solutions are written in python because it is arguably one of the easiest languages to master interview questions in – meaning you may have a higher chance of dominating the interview!

In this article, we will be using Regular Expressions to solve each problem. I hope you’re as excited as I am. So, without further adieu, let’s begin!

Question #1 – Disemvowel Trolls

Trolls are attacking your comment section!

A common way to deal with this situation is to remove all of the vowels from the trolls’ comments, neutralizing the threat.

Your task is to write a function that takes a string argument and returns a new string with all vowels removed.

For example, the string “Hello World!” would become “Hll Wrld”.

Note: For this problem, ‘y’ is NOT considered a vowel.

Solution to Question #1

This doesn’t look too bad, does it? Let’s jump right in!

Here is what the skeleton of the solution looks like:

def disemvowel(string_): """Removes all occurences of vowels from the string. Args: string_ (str): The input string. Returns: (str): The string with vowels removed. """

When I first began coding, my instinct for this solution would have been to create a temporary string, loop through the input string, and concatenate every letter that isn’t a vowel onto the temp string before returning it. However, programmers are smart folk – I’ll bet you can already tell me that this isn’t the most efficient solution.

Use a Regular Expression

We can use a Regular Expression (RegEx) to greatly reduce the complexity of the solution. Our goal is to replace every vowel (lower and uppercase) with a blank space. We can use the regular expression ‘substitute‘ operation to replace all the vowels with a blank space.

Substitute Operation

The substitute operation has 3 arguments we’ll be using:

re.sub(pattern, replacement, input_string)

Return the string obtained by replacing the leftmost non-overlapping occurrences of pattern in input_string with replacement. If the pattern isn’t found, input_string is returned unchanged.” – Python Docs

In python, RegEx uses the “re” class, so let’s be sure to import that into our code:

import re
VOWELS_REGEX = r"[aeiouAEIOU]" def disemvowel(string_): return re.sub(VOWELS_REGEX, "", string_) if __name__ == '__main__': print(disemvowel("Programming With Mosh Rocks!"))

Output:

Prgrmmng Wth Msh Rcks!

———————————————————————-

The VOWELS_REGEX variable is, of course, used to find the vowels in the string. To make a regex pattern, we start the string with an ‘r’ to tell python to create a “raw string pattern”. This lets us use escape characters, or “”,  in our patterns followed by regex special characters.

Next, we use a regex metacharacter (a character with a special meaning). In this case, we use the metacharacter “[]”, which contains a set of characters that will match any character inside of it. For example, “[0-9a-zA-Z]” means it will match all numbers from 0 to 9 and all lowercase and uppercase letters from a-z. I’m sure you noticed using ranges in a set decreased the number of characters you need to type out.

Regex Metacharacters

The code works! Great job ?

Question #2 – Find Valid Phone Number

Write a function that accepts a string and searches it for a valid phone number.

Return the phone number if found.

A valid phone number may be one of the following:

  • (xxx)-xxx-xxxx
  • xxx-xxx-xxxx

Solution to Question #2

Here is what the skeleton of the solution looks like:

def find_valid_phone(text): """ check text for phone number in either following format: - (xxx)-xxx-xxxx - xxx-xxx-xxxx Args: text (str): random string Returns: phone (bool): a valid phone number in the required format """

Search Operation

To solve this problem, we’ll be using the regular expression operation, “search” to find the pattern (phone number) in the text.

The search operation has 2 arguments we’ll be using:

re.search(pattern, string)

“Scan through string looking for the first location where the regular expression pattern produces a match, and return a corresponding match object. Return None if no position in the string matches the pattern.” – Python Docs

Here is the solution:

import re
def find_valid_phone(text): PHONE_REGEX = r'(d{3}|(d{3}))-d{3}-d{4}' phone = re.search(PHONE_REGEX, text) if phone != None: return phone.group() if __name__ == '__main__': print(find_valid_phone('Call me at 415-555-1011 tomorrow.')) print(find_valid_phone('My number is (212)-543-2212 tomorrow.'))

Output:

415-555-1011

(212)-543-2212

———————————————————————-

The PHONE_REGEX variable is used to find the phone number. Again, we start it with ‘r’ to signify the creation of a raw string.

To start with, we use a parenthesis (which is the beginning of a group in Regex. I’ll explain why in a minute.

Then, we use a ‘’, which is an escape character. It signifies the beginning of a special regex sequence and follows with a character that has a special meaning.

Regex Special Characters

We follow the escape character by a ‘d{3}’, which means ‘match 3 digits’. This will match the first 3 digits of the phone number with the format “xxx”. But what about the other format?

To match the other format, we need to use the pipe (‘|’), because we want to find “xxx” OR “(xxx)”. Be sure to keep both formats inside of the group we created at the beginning of the pattern.

Follow that by the escape character “” and “(“, which looks for literal parentheses. If you don’t use the escape character before the parentheses, it will assume you are starting another group.

Finally, we finish the pattern with a “-” and more “digit” special characters (followed by how many digits to match it to, {3} and {4}).

Remember, the search operator returns a match object. In order to get the phone number out of the match object, access it using the group operator. Pass an int argument to the operator to denote which group to return. You can make new groups by surrounding characters with parentheses inside a pattern. By default, The entire match is the zeroth group, accessed by either “match.group()” or “match.group(0)“.

That’s it! The code works. Do you feel more confident with regex yet? Just in case, let’s do more!

Question #3 – Strong Password Detector

Write a function that employs regular expressions to ensure the password given to the function is strong.

A strong password is defined as follows:

    • at least eight characters long
    • contains one uppercase character
    • contains one lowercase character
    • has at least one digit
    • has at least one special character

You may need to test the string against multiple regex patterns to validate its strength.

Solution to Question #3

At first glance, this problem looks a lot harder than the previous one. In actuality, it’s just as simple (just longer).

Here is what the skeleton of the solution looks like:

def validate_password(password): """ check for - at least eight characters long - contains uppercase character - contains lowercase character - has at least one digit - has at least one special character Args: password (str): password as string Returns: (bool): True if password is strong, else False """

To solve this problem, we’ll be using the regex “search” operator again to ensure that each pattern (password criteria) is fulfilled.

import re def validate_password(password): # REGEX PATTERN THAT CHECKS PASSWORD HAS AT LEAST 8 CHARACTERS at_least_8 = r".{8,}" # REGEX PATTERN THAT CHECKS PASSWORD HAS 1 LOWERCASE one_lowercase = r"[a-z]" # REGEX PATTERN THAT CHECKS PASSWORD HAS 1 UPPERCASE one_uppercase = r"[A-Z]" # REGEX PATTERN THAT CHECKS PASSWORD HAS 1 DIGIT one_digit = r"d" # REGEX PATTERN THAT CHECKS PASSWORD HAS 1 SPECIAL CHARACTER special_characters = r"!”#$%&'()*+,-./:;<=>?@[]^_`{|}~" if re.search(at_least_8, password) == None: print('Error: Password must have at least 8 characters') return False elif re.search(one_lowercase, password) == None: print('Error: Password must have at least 1 lowercase character') return False elif re.search(one_uppercase, password) == None: print('Error: Password must have at least 1 uppercase character') return False elif re.search(one_digit, password) == None: print('Error: Password must have at least 1 digit') return False elif re.search(special_characters, password) == None: print('Error: Password must have at least 1 special character') return False return True if __name__ == '__main__': print(validate_password('pass')) print(validate_password('PASSWORD')) print(validate_password('password')) print(validate_password('Password')) print(validate_password('Password77')) print(validate_password('Password-77'))

Output:

Error: Password must have at least 8 characters
False

Error: Password must have at least 1 lowercase character
False

Error: Password must have at least 1 uppercase character
False

Error: Password must have at least 1 digit
False

Error: Password must have at least 1 special character
False

True

———————————————————————-

Remember, you may use the pipe to find pattern1 OR pattern2 in a string. But, if you want to ensure pattern1 AND pattern2 are fulfilled in a string, we’ve got to split them up. We’ll be splitting the five criteria into five different patterns.

Begin by creating a pattern that checks for a minimum of 8 characters. To do this, we use “.” to check for any character, and the “{8, }” to check that there is a minimum of 8 of them (with no maximum value specified).

Then, create a pattern that checks for a lower case character. We use the lowercase letters from “a-z” inside of a set to check for this.

Next, make a pattern to check for an uppercase character. We use the uppercase letters from “A-Z” inside of a set to do this.

Next, we check for a digit (“d”).

For the final pattern, we check for a special character. The OWASP recommends the following list of special characters for passwords:” !”#$%&'()*+,-./:;<=>?@[]^_`{|}~”. We can put these characters inside of a set to search for them in the provided password.

We’ll use these patterns in five separate searches to see if each criterion is met. If even one of the match regexes returns None, we’ll know the password is NOT strong and to return False. Else, we return True.

Our job is done!

Summary

Regular expressions are incredibly powerful tools that every developer should be proficient in. Unfortunately, most do not take the time to learn it well. Do your future self a favor and learn them early – you will be thanking your current self in the future ?

I’ll be back soon to write more articles with detailed explanations of random interview questions. I hope you enjoyed it!

If you’re looking for a course to master Python and increase your salary potential in the process, I recommend Mosh’s course linked below:

Complete Python Mastery – Code With Mosh

John Calderaio
I studied Computer Science at the University of Florida Herbert Wertheim College of Engineering. My interests include music, writing, coding, and video games. I live in Palm Beach, Florida with my wife, Estefania.

Tags: Interview, python, regex