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 thesplit()
by default, then usecapitalize()
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(" "))