Counting ways to divide a word into palindrome blocks I wrote this program as a solution to the 2015 British Informatics Olympiad question on &quot;block&quot; palindromes.
Brief overview of the task:

A palindrome is a word that shows the same sequence of letters when reversed.
If a word can have its letters grouped together in two or more blocks (each containing one or more adjacent letters) then it is a block palindrome if reversing the order of those blocks results in the same sequence of blocks.
For example, using brackets to indicate blocks, the following are block palindromes:

BONBON can be grouped together as (BON)(BON);
ONION can be grouped together as (ON)(I)(ON);
BBACBB can be grouped together as (B)(BACB)(B) or (BB)(AC)(BB) or (B)(B)(AC)(B)(B)

Note that (BB)(AC)(B)(B) is not valid as the reverse (B)(B)(AC)(BB) shows the blocks in a different order.
TASK: Write a program which reads in a word of between 2 and 10 (inclusive) uppercase letters.
You should output a single number, the number of different ways the input can be grouped to show it is a block palindrome.

What tips do you have for improving my solution:
# theonlygusti's solution to Question 1(a)

word = input()

if not (2 &lt;= len(word) &lt;= 10):
    print(&quot;Your input must be between 10 and 2 characters, inclusive.&quot;)
    exit()

if not word.upper() == word:
    print(&quot;Your input must be all uppercase, e.g. BBACBB&quot;)
    exit()

if not word.isalpha():
    print(&quot;Your input must contain only letters, this means characters like numbers and spaces are not allowed.&quot;)
    exit()

def number_of_block_palindrome_groupings(string):
    total_groupings = 0
    for i in range(1, len(string)//2+1):
        if (string[:i] == string[-i:]):
            total_groupings += 1 + number_of_block_palindrome_groupings(string[i:-i])
    return total_groupings

print(number_of_block_palindrome_groupings(word))
Exit code

When exiting due to an error, it's good to use a non-zero exit code.
Calling exit() without an explicit value will use the default 0, meaning success.

Naming

The name number_of_block_palindrome_groupings is a bit long an tedious.
How about count_block_palindromes?

List comprehensions

Instead of accumulating a sum with a loop,
you could use a list comprehension:

return sum([1 + count_block_palindromes(string[i:-i])
            for i in range(1, len(string) // 2 + 1)
            if string[:i] == string[-i:]])


Memoization

In case of long input with recursive patterns,
the same substrings may be computed many times repeatedly.
It could be a useful optimization to cache the results of computing each unique input.
An easy way to implement that using functools.lru_cache.

import functools


@functools.lru_cache()
def count_block_palindromes(string):
    # ...


Doc tests

Doc tests are awesome. They are executable documentations serving as unit tests, for example:

def count_block_palindromes(string):
    """
    &gt;&gt;&gt; count_block_palindromes("BONBON")
    1

    &gt;&gt;&gt; count_block_palindromes("ONION")
    1

    &gt;&gt;&gt; count_block_palindromes("BBACBB")
    3

    &gt;&gt;&gt; count_block_palindromes("BABABABABABABABA")
    15

    &gt;&gt;&gt; count_block_palindromes("BABABABABABABAB")
    33

    """
    # ... the code


This is runnable in Pycharm with Control Shift R,
or in the shell with python -mdoctest yourscript.py.