HackerRank: Capitalize! Notes

Background

This article was written down when I was doing a Python challenge on HackerRank: Capitalize!. It was not a hard problem, but I got the "Wrong Answer" three times...

The main problem is that I am not familiar with the title(), capitalize(), and string.capwords().

Problem

The problem gives you a string S and requires you to capitalize the first character of each word in S where \( 0 \lt len(S) \lt 1000\). The string will only contain alphanumeric characters and spaces.

We need to be careful that only the first character is capitalized. If the input is "12abc", then the output should remain "12abc".

Analysis

title()

The first thing I try is title(), but it fails in a special situation.

1a 2b
def solve(s):
    return s.title()

#Output:1A 2B

We can see that title will capitalize the first letter found in the word.

split(sep=None, maxsplit=-1)

As I mentioned in this article, split() will take consecutive whitespace as a single separator for default.

For example:

s = "tom   and jerry"
l = s.split()

print(l)

Output:

['tom', 'and', 'jerry']

Here we do not pass anything to the split()'s argument sep. You can see that there are 2 whitespaces between the "tom" and "and" strings. However, the split() will treat consecutive whitespace as one single separator when sep is not specified or is None.

The result will be different if we set the sep as ' ' (one whitespace):

s = "tom   and jerry"
l = s.split(' ')

print(l)

Output:

['tom', '', '', 'and', 'jerry']

This is how split() works by using one whitespace as the separator.

The good thing about this is that after we process the elements in the list, we can use "".join(s)to connect them without changing the whitespace between words.

For instance:

s = "tom   and jerry"
l = s.split(' ')

print(l)
print(" ".join(l))

Output:

['tom', '', '', 'and', 'jerry']
tom   and jerry

However, if the sep is None or not specified:

s = "tom   and jerry"
l = s.split()

print(l)
print(" ".join(l))

Output:

['tom', 'and', 'jerry']
tom and jerry

We can see only one whitespace will be used to join the elements here.

capitalize()

capitalize() will return a copy of the string with its first character capitalized, and the rest remain lowercase.

This is basically what we want.

But when I was writing the solution using capitalize(), I did not notice the problems caused by split(), so I got the "Wrong Answer" by this code:

def solve():
    l = s.split()
    for i in range(len(l)):
        l[i] = l[i].capitalize()
    return " ".join(l)

If we meet a situation like the "tom  and jerry" case, this solution will fail. Because we should output:

Tom  and Jerry

But this solution will give

Tom and Jerry

which does not contain the extra whitespace.

string.capwords(s, sep=None)

string.capwords(s, sep) have two parameters. One is s, and the other is sep. s is the string we want to process, sep is the same as the one used in split() parameters, which is the separator.

string.capwords(s,sep=None) works in this way: it will split the s using split(sep), capitalize each word using capitalize(), and join the capitalized words using join.

If the sep argument is absent or None, it will also take consecutive whitespace characters as a single space and remove leading and trailing whitespace.

In short:

  • If sep is absent, it will use the split() by default, then use capitalize() to capitalize words, and join the words by one space.
  • If sep is given, sep will be used to split and join the capitalized words.
import string

s = "tom   and jerry"
print(string.capwords(s))

#Output:Tom And Jerry

If we set sep as " " (one whitespace):

import string

s = "tom   and jerry"
print(string.capwords(s, " "))

#输出:Tom   And Jerry

This is exactly what we want.

Solution

Therefore, this is my final answer:

import string

def solve(s):
    return string.capwords(s," ")

We can also modify the previous method:

def solve(s):
    return " ".join(word.capitalize() for word in s.split(" "))

Reference

  1. Python str.title()
  2. Python str.split()
  3. Python str.capitalize()
  4. Python string.capwords()