Skip to content

S3Q1 · Analyze Sentences

⚡ Quick Reference

Function: process_sentence(sentence: str, task: str)

Four tasks, one dispatcher:

def process_sentence(sentence: str, task: str):
    words = sentence.split()

    if task == "count_words":
        return len(words)

    elif task == "count_palindrome_words":
        return sum(1 for w in words if w == w[::-1])

    elif task == "count_words_with_repeated_chars":
        return sum(1 for w in words if len(set(w)) < len(w))

    elif task == "words_with_max_len":
        max_len = max(len(w) for w in words)
        return {w for w in words if len(w) == max_len}

Key rules: - w == w[::-1] → palindrome check - len(set(w)) < len(w) → has repeated characters (set removes duplicates, so if shorter than original, there were repeats) - words_with_max_len returns a set, not a list


Problem Statement

Problem

Write a function process_sentence(sentence, task) that performs one of four analyses on a sentence depending on task:

task Returns
"count_words" Total number of words
"count_palindrome_words" Number of palindrome words
"count_words_with_repeated_chars" Number of words with at least one repeated character
"words_with_max_len" A set of the longest word(s)

Examples:

Input
sentence = "level noon civic radar something"
task = "count_words"
Output
5
Input
sentence = "level noon civic radar something"
task = "count_palindrome_words"
Output
4
Input
sentence = "hello world programming fun and interesting"
task = "count_words_with_repeated_chars"
Output
3
Input
sentence = "hello world programming fun and interesting"
task = "words_with_max_len"
Output
{'interesting', 'programming'}

Breaking down each task

Task 1 - count_words

Simply count the words after splitting:

words = sentence.split()
return len(words)

sentence.split() splits on any whitespace and handles multiple spaces gracefully.


Task 2 - count_palindrome_words

A word is a palindrome if it reads the same forwards and backwards:

w == w[::-1]
Word w[::-1] Palindrome?
"level" "level" ✅ Yes
"noon" "noon" ✅ Yes
"civic" "civic" ✅ Yes
"radar" "radar" ✅ Yes
"something" "gnihtemos" ❌ No

Count: 4

[::-1] for palindrome check

w[::-1] reverses the string. If the reversed string equals the original, it's a palindrome. This is the cleanest one-liner palindrome check in Python.


Task 3 - count_words_with_repeated_chars

A word has repeated characters if any character appears more than once. The elegant way to check: convert to a set and compare lengths.

len(set(w)) < len(w)

If set(w) is shorter than w, at least one character was a duplicate.

Word len(w) len(set(w)) Repeated?
"hello" 5 4 ({h,e,l,o}) ✅ Yes (l repeated)
"world" 5 5 ({w,o,r,l,d}) ❌ No
"programming" 11 8 ({p,r,o,g,a,m,i,n}) ✅ Yes (r,g,m repeated)
"fun" 3 3 ❌ No
"and" 3 3 ❌ No
"interesting" 11 7 ({i,n,t,e,r,s,g}) ✅ Yes

Count: 3

set length trick

len(set(w)) < len(w) is the most Pythonic way to check for duplicates in any sequence. A set can only hold unique elements - if the set is smaller than the original, there were duplicates.


Task 4 - words_with_max_len

Find the length of the longest word, then collect all words matching that length into a set:

max_len = max(len(w) for w in words)
return {w for w in words if len(w) == max_len}

For "hello world programming fun and interesting":

Word Length
"hello" 5
"world" 5
"programming" 11 ← max
"fun" 3
"and" 3
"interesting" 11 ← max

max_len = 11 → result: {'programming', 'interesting'}

The result is a set - order is not guaranteed, and that is expected.


Solution approaches

def process_sentence(sentence: str, task: str):
    words = sentence.split()

    if task == "count_words":
        return len(words)

    elif task == "count_palindrome_words":
        count = 0
        for w in words:
            if w == w[::-1]:
                count += 1
        return count

    elif task == "count_words_with_repeated_chars":
        count = 0
        for w in words:
            if len(set(w)) < len(w):
                count += 1
        return count

    elif task == "words_with_max_len":
        max_len = max(len(w) for w in words)
        result = set()
        for w in words:
            if len(w) == max_len:
                result.add(w)
        return result
def process_sentence(sentence: str, task: str):
    words = sentence.split()

    if task == "count_words":
        return len(words)

    elif task == "count_palindrome_words":
        return sum(1 for w in words if w == w[::-1])

    elif task == "count_words_with_repeated_chars":
        return sum(1 for w in words if len(set(w)) < len(w))

    elif task == "words_with_max_len":
        max_len = max(len(w) for w in words)
        return {w for w in words if len(w) == max_len}

sum(1 for w in words if condition) is the idiomatic way to count items satisfying a condition - cleaner than maintaining a counter variable.

def is_palindrome(w):
    return w == w[::-1]

def has_repeated_chars(w):
    return len(set(w)) < len(w)

def process_sentence(sentence: str, task: str):
    words = sentence.split()

    if task == "count_words":
        return len(words)
    elif task == "count_palindrome_words":
        return sum(1 for w in words if is_palindrome(w))
    elif task == "count_words_with_repeated_chars":
        return sum(1 for w in words if has_repeated_chars(w))
    elif task == "words_with_max_len":
        max_len = max(len(w) for w in words)
        return {w for w in words if len(w) == max_len}

The problem explicitly allows helper functions. Extracting is_palindrome and has_repeated_chars makes the main function easier to read and each helper independently testable.

def process_sentence(sentence: str, task: str):
    words = sentence.split()

    def count_words():
        return len(words)

    def count_palindrome_words():
        return sum(1 for w in words if w == w[::-1])

    def count_words_with_repeated_chars():
        return sum(1 for w in words if len(set(w)) < len(w))

    def words_with_max_len():
        max_len = max(len(w) for w in words)
        return {w for w in words if len(w) == max_len}

    dispatch = {
        "count_words": count_words,
        "count_palindrome_words": count_palindrome_words,
        "count_words_with_repeated_chars": count_words_with_repeated_chars,
        "words_with_max_len": words_with_max_len,
    }
    return dispatch[task]()

Maps task strings to inner functions and calls the right one. Avoids a long if-elif chain - useful when the number of tasks grows large. Advanced but clean.

def process_sentence(sentence: str, task: str):
    words = sentence.split()

    if task == "count_words":
        return len(words)

    elif task == "count_palindrome_words":
        return len(list(filter(lambda w: w == w[::-1], words)))

    elif task == "count_words_with_repeated_chars":
        return len(list(filter(lambda w: len(set(w)) < len(w), words)))

    elif task == "words_with_max_len":
        max_len = max(map(len, words))
        return set(filter(lambda w: len(w) == max_len, words))

filter(lambda w: condition, words) replaces the comprehension - keeps only words satisfying the condition. len(list(...)) counts them. For words_with_max_len, map(len, words) computes all lengths in one pass, and filter selects the longest words. Pure functional style throughout.


Key takeaways

01

w == w[::-1] for palindromes

Reversing with [::-1] and comparing is the one-liner palindrome check. Works for any sequence - strings, lists, tuples.

02

len(set(w)) < len(w) for duplicates

Converting to a set removes duplicates. If the set is smaller than the original, duplicates existed. Works for any iterable, not just strings.

03

sum(1 for x in iterable if cond)

The idiomatic way to count items satisfying a condition. Equivalent to a counter loop but cleaner. Memorise this pattern - it appears constantly.