Skip to content

S2Q1 · Count Words with Matching First/Last but Different Second/Second-Last

⚡ Quick Reference

Function: count_special(words: list) -> int

Core idea: for each word, check if first == last AND second != second-last (case-insensitive).

def count_special(words):
    count = 0
    for w in words:
        w = w.lower()
        if w[0] == w[-1] and w[1] != w[-2]:
            count += 1
    return count

Key rules: - Case-insensitive → lowercase the whole word first - Condition 1: w[0] == w[-1] (first == last) - Condition 2: w[1] != w[-2] (second ≠ second-last) - Both must hold; each word has at least 2 characters


Problem Statement

Problem

Write a function count_special(words) that counts how many words have the same first and last character AND different second and second-last characters (case-insensitively).

Examples:

Input
["Bulb", "deed", "civic", "Noon", "lol"]
Output
1
Input
["abca", "aXba", "xyzzyx", "abcaXab"]
Output
2

Tracing both examples

Example 1: ["Bulb", "deed", "civic", "Noon", "lol"]

Word lowered w[0]==w[-1]? w[1]!=w[-2]? Count?
"Bulb" "bulb" b==b ✅ u!=l ✅
"deed" "deed" d==d ✅ e!=e ❌
"civic" "civic" c==c ✅ i!=i ❌
"Noon" "noon" n==n ✅ o!=o ❌
"lol" "lol" l==l ✅ o!=o ❌

Count = 1

Example 2: ["abca", "aXba", "xyzzyx", "abcaXab"]

Word lowered [0]==[−1]? [1]!=[−2]? Count?
"abca" "abca" a==a ✅ b!=c ✅
"aXba" "axba" a==a ✅ x!=b ✅
"xyzzyx" "xyzzyx" x==x ✅ y!=y ❌
"abcaXab" "abcaxab" a!=b ❌ -

Count = 2


Solution approaches

def count_special(words):
    count = 0
    for w in words:
        w = w.lower()
        if w[0] == w[-1] and w[1] != w[-2]:
            count += 1
    return count
def count_special(words):
    def is_special(w):
        w = w.lower()
        return w[0] == w[-1] and w[1] != w[-2]
    return sum(1 for w in words if is_special(w))
def count_special(words):
    is_special = lambda w: (
        (lambda lw: lw[0] == lw[-1] and lw[1] != lw[-2])(w.lower())
    )
    return len(list(filter(is_special, words)))
def count_special(words):
    check = lambda w: (lambda lw: lw[0]==lw[-1] and lw[1]!=lw[-2])(w.lower())
    return sum(map(check, words))

map(check, words) produces True/False for each word; sum() counts the True values.


Key takeaways

01

Lowercase the whole word once

w = w.lower() upfront makes all four index accesses case-insensitive without repeated .lower() calls per character. One conversion covers all conditions.

02

w[1] and w[-2] - second and second-last

w[1] is the second character; w[-2] is the second-to-last. For a 2-character word like "ab", w[1] == w[-2] (both index position 1 and -1 from the end coincide at index 1) - this correctly handles the edge case.

03

Short-circuit and - skip second check if first fails

w[0] == w[-1] and w[1] != w[-2] - if the first/last don't match, the second condition is never evaluated. Words failing condition 1 are skipped efficiently.