5 Best Ways to Check if Strings Are Rotations of Each Other in Python

Rate this post

πŸ’‘ Problem Formulation: In Python, given two strings, we often need to determine if they are rotations of each other. This means that by cyclically moving the characters of one string, we can obtain the other string. For example, “abcde” and “deabc” are rotations of each other, whereas “abcde” and “edcba” are not.

Method 1: Use of Concatenation and in Operator

This method involves concatenating the original string with itself and then checking if the second string is a substring of the result using Python’s in operator. This method is straightforward and leverages Python’s powerful string handling features.

Here’s an example:

def are_rotations(str1, str2):
    if len(str1) == len(str2) and str2 in (str1 + str1):
        return True
    else:
        return False

print(are_rotations('abcde', 'deabc'))  # Output: True
print(are_rotations('abcde', 'edcba'))  # Output: False

The first example returns True indicating ‘abcde’ and ‘deabc’ are rotations of each other, while the second returns False showing ‘abcde’ and ‘edcba’ are not.

This method quickly checks if two strings are rotations by leveraging the simplicity of Python’s string concatenation and substring verification. However, concatenating a string with itself could be memory-intensive for very long strings.

Method 2: Using Iterative Comparison

This method involves iteratively checking all rotations of the first string to see if it matches the second string. It has the advantage of avoiding extra memory usage due to concatenation but can be less efficient due to its O(n^2) complexity.

Here’s an example:

def are_rotations_iterative(str1, str2):
    if len(str1) != len(str2):
        return False
    for i in range(len(str1)):
        if str1[i:] + str1[:i] == str2:
            return True
    return False

print(are_rotations_iterative('abcde', 'deabc'))  # Output: True
print(are_rotations_iterative('abcde', 'edcba'))  # Output: False

The first call prints True, confirming that ‘abcde’ is a rotation of ‘deabc’, whereas the second call prints False, as ‘abcde’ is not a rotation of ‘edcba’.

While this method directly tackles the problem without resorting to creating additional strings, it is computationally expensive for larger strings due to its iterative nature.

Method 3: Zip and Any Functions

This method harnesses Python’s zip and any functions to check for rotations. It’s relatively efficient, as it stops checking as soon as a match is found.

Here’s an example:

def are_rotations_zip(str1, str2):
    if len(str1) != len(str2):
        return False
    return any(str1 == str2[i:] + str2[:i] for i in range(len(str1)))

print(are_rotations_zip('abcde', 'deabc'))  # Output: True
print(are_rotations_zip('abcde', 'edcba'))  # Output: False

By using any, this method efficiently checks each rotation and quickly returns a result as soon as a rotation match is found.

This method is both memory and computation efficient and leverages Python’s built-in functions to deliver concise and idiomatic code.

Method 4: Utilizing Slicing and Itertools

By using the slicing feature and the itertools library, we can cleverly generate all the rotations of the first string and verify a match with the second string.

Here’s an example:

import itertools

def are_rotations_itertools(str1, str2):
    if len(str1) != len(str2):
        return False
    str1_rotations = itertools.permutations(str1, len(str1))
    return any(''.join(rotation) == str2 for rotation in str1_rotations)

print(are_rotations_itertools('abcde', 'deabc'))  # Output: True
print(are_rotations_itertools('abcde', 'edcba'))  # Output: False

The function uses itertools to generate permutations and then checks for equality with the second string.

This method, though not the most efficient for checking rotations, showcases Python’s ability to generate permutations easily. It is suitable for shorter strings but becomes less practical as the string length increases.

Bonus One-Liner Method 5: Use of List Comprehension

For the succinct code lovers, this one-liner combines Python’s list comprehension with the string slicing feature for a compact rotation check.

Here’s an example:

are_rotations_oneliner = lambda str1, str2: len(str1) == len(str2) and any(str1 == str2[i:] + str2[:i] for i in range(len(str1)))

print(are_rotations_oneliner('abcde', 'deabc'))  # Output: True
print(are_rotations_oneliner('abcde', 'edcba'))  # Output: False

This one-liner outputs True for the first call and False for the second, indicating whether the strings are rotations of each other or not.

This elegant solution is both succinct and efficient. However, it might sacrifice readability for less experienced Python programmers and is not recommended for highly readable code bases.

Summary/Discussion

  • Method 1: Concatenation and in Operator. Simple and direct. Can be memory-intensive for long strings.
  • Method 2: Iterative Comparison. Avoids extra memory use. Less efficient due to O(n^2) time complexity.
  • Method 3: Zip and Any Functions. Memory and computation efficient. Leverages Python’s built-in functions for concise code.
  • Method 4: Utilizing Slicing and Itertools. Demonstrates flexibility with permutations. Not suitable for long strings due to scaling issues.
  • Bonus Method 5: One-Liner with List Comprehension. Compact and efficient. Can reduce readability for novice programmers.