← Back to DevBytes

Solving Count and Say in Python: Step-by-Step Guide

Introduction to the Count and Say Problem

The Count and Say sequence is a classic algorithm problem that frequently appears in coding interviews and competitive programming challenges. It is a sequence of integers where each term is generated by describing the previous term in terms of consecutive digit counts. Despite its apparent simplicity, the problem tests a developer's ability to manipulate strings, handle edge cases, and write clean, efficient code.

In this tutorial, you will learn what the Count and Say sequence is, why it matters, how to implement it in Python step by step, and the best practices to follow when solving similar problems.

What Is the Count and Say Sequence?

The Count and Say sequence starts with the string "1". Each subsequent term is produced by reading the previous term aloud and describing the count of consecutive identical digits. For example:

Given a positive integer n, the task is to return the nth term of this sequence as a string.

Why the Count and Say Problem Matters

While the Count and Say sequence may seem like a puzzle, it carries real value for developers for several reasons:

How to Solve Count and Say in Python

Step 1: Understand the Recurrence

The key insight is that each term depends only on the previous term. Therefore, you can start from "1" and iteratively build up to the nth term. For each term, scan the current string, count consecutive identical digits, and append the count followed by the digit to the result.

Step 2: Write the Core Logic

Here is a clean iterative implementation:

def countAndSay(n: int) -> str:
    if n <= 0:
        return ""

    current = "1"

    for _ in range(1, n):
        next_term = []
        i = 0
        while i < len(current):
            count = 1
            while i + 1 < len(current) and current[i] == current[i + 1]:
                count += 1
                i += 1
            next_term.append(str(count))
            next_term.append(current[i])
            i += 1
        current = "".join(next_term)

    return current

Let us break down what happens here. The outer loop runs n - 1 times because the first term is already known. Inside, we use a list next_term to accumulate characters, which is more efficient than repeated string concatenation. The inner while loop counts consecutive identical digits, then we append both the count and the digit to the result.

Step 3: Test the Implementation

Always verify your solution with known outputs:

for i in range(1, 7):
    print(f"n={i}: {countAndSay(i)}")

Expected output:

n=1: 1
n=2: 11
n=3: 21
n=4: 1211
n=5: 111221
n=6: 312211

Step 4: Add Input Validation

Robust code should handle invalid inputs gracefully:

def countAndSaySafe(n: int) -> str:
    if not isinstance(n, int) or n <= 0:
        raise ValueError("n must be a positive integer")

    current = "1"
    for _ in range(1, n):
        next_term = []
        i = 0
        while i < len(current):
            count = 1
            while i + 1 < len(current) and current[i] == current[i + 1]:
                count += 1
                i += 1
            next_term.append(str(count))
            next_term.append(current[i])
            i += 1
        current = "".join(next_term)

    return current

Alternative Approaches

Using itertools.groupby

Python's standard library offers itertools.groupby, which groups consecutive identical elements. This leads to a more concise solution:

from itertools import groupby

def countAndSayGroupby(n: int) -> str:
    current = "1"
    for _ in range(1, n):
        current = "".join(
            str(len(list(group))) + digit
            for digit, group in groupby(current)
        )
    return current

This version is elegant and Pythonic, but it may be slightly slower for very large inputs because list(group) materializes each group in memory.

Recursive Solution

You can also express the recurrence recursively:

def countAndSayRecursive(n: int) -> str:
    if n == 1:
        return "1"

    previous = countAndSayRecursive(n - 1)
    result = []
    i = 0
    while i < len(previous):
        count = 1
        while i + 1 < len(previous) and previous[i] == previous[i + 1]:
            count += 1
            i += 1
        result.append(str(count))
        result.append(previous[i])
        i += 1
    return "".join(result)

While recursion mirrors the mathematical definition closely, it risks hitting Python's recursion limit for large n. The iterative approach is generally preferred.

Best Practices

Performance Considerations

The length of the nth term grows approximately by a factor of 1.3035 each step, a value related to the Conway constant. This means that for n = 30, the resulting string can already be thousands of characters long. If you need to compute many terms, consider caching results or precomputing them once.

from functools import lru_cache

@lru_cache(maxsize=None)
def countAndSayCached(n: int) -> str:
    if n == 1:
        return "1"
    previous = countAndSayCached(n - 1)
    result = []
    i = 0
    while i < len(previous):
        count = 1
        while i + 1 < len(previous) and previous[i] == previous[i + 1]:
            count += 1
            i += 1
        result.append(str(count))
        result.append(previous[i])
        i += 1
    return "".join(result)

Using lru_cache avoids recomputing earlier terms when the function is called multiple times with different values of n.

Conclusion

The Count and Say problem is a deceptively simple exercise that strengthens your grasp of string manipulation, iterative algorithms, and careful edge case handling. By starting from the base case of "1" and repeatedly describing each term, you can build the sequence efficiently in Python. Whether you choose a straightforward iterative loop, a concise groupby solution, or a cached recursive approach, the key is to write clear, validated, and performant code. Mastering this problem will not only prepare you for interviews but also sharpen the fundamental skills you need for more complex algorithmic challenges.

— Ad —

Google AdSense will appear here after approval

← Back to all articles