Weekly Leetcode/HackerRank Question: Dissecting the Pangram Checker

Weekly Leetcode/HackerRank Question: Dissecting the Pangram Checker

Problem 1

Hey there, fellow code enthusiast! I am starting a new series of blog posts where I answer LeetCode/HackerRank questions. The problem will be explained in this post but feel free to check out the problem on the website. I will link the question below:

HackerRank - Pangrams

Today we’re diving deep into a question about pangrams. So, what's a pangram, you ask?

What’s in a Pangram?

A pangram is a neat little thing—it's a sentence that contains every letter from the English alphabet at least once. You might've come across the classic example: “The quick brown fox jumps over the lazy dog”. Today, we're tasked with creating a tool that can identify if a given sentence is one of these special strings or not.

Understanding the Problem

The challenge is pretty clear: We're given a sentence, and we need to check if it’s a pangram. If it is, our function should return the string "pangram", and if it isn't, it should return "not pangram". Sounds simple, right?

From the examples, it's clear that casing doesn't matter—whether letters are uppercase or lowercase is irrelevant to our pangram status. But there's a catch: every single letter in the English alphabet needs to be in there. Missing even one means our sentence isn't a pangram.

Alright, let's dive into my original solution

import string

def pangrams(s):
    # We start by creating a list of all lowercase letters in the English alphabet.
    alphabet_list = list(string.ascii_lowercase)

    # Convert the input string to lowercase. This ensures we're not caught out by casing differences.
    s = s.lower()

    # Loop through each letter in our input string.
    for letter in s:
        # If the letter is in our alphabet list, we remove it.
        # This is akin to ticking off each letter as we encounter it.
        if letter in alphabet_list:
            alphabet_list.remove(letter)

    # If our alphabet list is empty, it means we've seen every letter in our input string.
    # Hence, it's a pangram.
    if alphabet_list == []:
        return 'pangram'
    else:
        # If there are any letters left, our input string missed some. 
        # So, it's not a pangram.
        return 'not pangram'

Breaking Down The Solution

I started with the entire lowercase English alphabet, and for every character in the sentence, I knocked them off the list. It's like having a checklist and crossing items off. If, in the end, all items are crossed off (or in this case, all letters are removed), then we know we've got ourselves a pangram.

Optimizing the Solution

As any good programmer should do, it's always a good idea to optimize the code. While doing this by yourself can be rewarding and it's a valuable skill, I often prefer to research and explore others solutions to see where I can improve. HackerRank lets you see others' responses in the discussion section. After doing so and asking ChatGPT for suggestions on how to optimize, this is what I have done to optimize.

My original approach is easy to understand and pretty efficient for shorter strings. However, one potential optimization is to use a set instead of a list for the alphabet_list. This would make the in and remove operations faster (constant time for sets versus linear time for lists). Here's an optimized version of my function with more succinct synatx as well:

def pangrams(s):
    # Using a set for faster lookup and removal.
    alphabet_set = set(string.ascii_lowercase)

    # Check off letters we encounter.
    for letter in s.lower():
        alphabet_set.discard(letter)

    # If our set is empty, it's a pangram.
    return 'pangram' if not alphabet_set else 'not pangram'

By switching to a set and using the discard method, we avoid potential slowdowns when dealing with large strings, and we also make the code slightly more concise. My approach is great for understanding the problem and finding a solution, but when thinking about optimization, sets can offer a neat advantage in this context.