Hackbright Code Challenges

Reverse Words: Solution

Reverse Words: Solution

Problem

Reverse Words

Whiteboard

Harder

Challenge

Medium

Concepts

Strings, Loops

Download

reverse-words-solution.zip


We can do this by “tokenizing” our string — converting it into a list of “tokens”, with each token being either a word or a series of spaces. Once we’ve done that, we can just reverse the list of tokens:

def rev(s):
    """Reverse word-order in string, preserving spaces."""

    # START SOLUTION

    # A token is either a word or a series of spaces --- so,
    # for example, we would turn "    hello kitty "
    # into the tokens = ["    ", "hello", " ", "kitty", " "].

    # The current token we're building up.
    current_token = ''

    # List of tokens found so far
    tokens = []

    # True when we're collecting spaces
    # False when we're collecting non-spaces
    in_space = None

    for letter in s:

        if letter == " ":
            if not in_space:
                # Switch from space -> letter: add the current
                # (letter-y) token and restart our current_token
                tokens.append(current_token)
                current_token = ''
                in_space = True

        else:
            if in_space:
                # Switch from letter -> space: add the current
                # (space-y) token and restart our current_token
                tokens.append(current_token)
                current_token = ''
                in_space = False

        # Add this letter to our current_token
        current_token += letter

    # Finished, add the ending token to our list
    tokens.append(current_token)

    # Reverse tokens as string ['hi', ' ', 'world'] -> "world hi"
    return ''.join(reversed(tokens))

Alternatively, if we split the string on spaces, we’ll get everything which appears in between consecutive spaces — even if that’s an empty string! Then we can just reverse the list and put the spaces back in:

def rev2(s):
    """Reverse word-order in string, preserving spaces."""

    # Splitting on space will give us both the words and empty strings - there
    # will be an empty string each time two spaces are next to each other
    #
    # Then we just reverse the order and put the spaces back in

    return " ".join(reversed(s.split(" ")))

Regular Expressions

While this problem is interesting and worthwhile to solve directly, as above, it could also be solved using regular expressions, a mini-language for text matching and replacement supported by Python’s re library:

import re

def rev(s):
    """Turn "    hello  kitty " -> " kitty  hello   "."""

    tokens = re.findall(" +|[^ ]+", s)
    return "".join(reversed(tokens))

(For people with some experience with regular expressions, you can read that as “Match as many spaces as possible or as many non-spaces as possible)

Regular expressions often provide terse but useful solutions for text matching.