Capitalizing the first letter of every word in a string (with arbitrary spacing) I solved the following question

You are asked to ensure that the first and last names of people begin
with a capital letter in their passports. For example, alison heck
should be capitalised correctly as Alison Heck.
Given a full name, your task is to capitalize the name appropriately.
Input Format
A single line of input containing the full name, S.
Constraints

0 &lt; len(S) &lt; 1000
The string consists of alphanumeric characters and spaces.

Note: in a word only the first character is capitalized.
Example 12abc when capitalized remains 12abc.
Output Format:
Print the capitalized string, S.

Here's my code:
#!/bin/python

import math
import os
import random
import re
import sys

# Complete the solve function below.
def solve(s):
    ls = s.split(&quot; &quot;)
    new_word = &quot;&quot;
    new_name = &quot;&quot;
    for word in ls:
        if len(word) &gt; 1:
            new_word = new_word + word[0].title() + word[1:] + &quot; &quot;
        else:
            new_word = new_word + word.title() + &quot; &quot;
    new_name = new_name.join(new_word) 
    return new_name

if __name__ == '__main__':
    fptr = open(os.environ['OUTPUT_PATH'], 'w')

    s = raw_input()

    result = solve(s)

    fptr.write(result + '\n')

    fptr.close()

I think I used a very long approach and would appreciate more efficient techniques to do the same.
The primary problem which I faced is handling arbitrary spaces and hence I went with this approach but the code smells bad. One things I can think of is reducing variables but that wouldn't be very helpful and make it less readable I think
EDIT : The question is  this question from HackerRank however the solution to this problem on the website does not include test cases where capitalize() and title() fail. The failing of these and more methods have also been discussed here
remove the unused imports

Your code logic is OK but the execution is not good. Try not to overcomplicate it. Take a piece of paper and write the procedure of how a human like YOU would do it, just with a pencil and paper.
read the names individually... make first character capital if it isn't a digit 

Now that you have  basic design, become more specific, or in Python terms

read the names individually for word in string.split()
make the first character capital: string.title()
if it isn't a digit : if not string[0].isdigit()


The primary problem which I faced is handling arbitrary spaces

string.split() will return the same thing, let it be 1 space or 1000 spaces. It does not matter
Now you have exactly what you need, it is just a matter of putting it together.
for every word in words, capitalize if the first character isn't a digit else do nothing

    return &quot; &quot;.join(word.title() if not word[0].isdigit() else word for word in words.split())

Furthermore, using capitalize() will avoid the extra check
    return &quot; &quot;.join(word.capitalize() for word in words.split(' '))

EDIT:
You have to use .split(' ') and NOT .split() since .split() removes all the whitespaces.

As you mentioned, title() and capitalize() fail for scenarios where you pass something like
ALLISON heck

Output
Allison Heck

In that case, you need to have extra checks. The best thing to do here is to create another function that specifically capitalizes the first letter
Here is what I thought of
def cap_first(word):
    return word[:1].upper() + word[1:]

the solve function remains the same
def solve(words):
    return ' '.join(cap_first(word) for word in words.split(' ')

Benchmarks
the latter code is surely more readable and compact, but what is its performance compared to the previous solution?
I will measure the execution time in the following manner using the time module
for iterations in (10 ** 5,11 ** 5, 10 ** 6, 11 ** 6):
    print(f&quot;\n{iterations} iteartions\n&quot;)


    start = time.time()
    for _ in range(iterations): solvenew(names)
    print(f&quot;Time taken for new function: {time.time() - start:.3f} s&quot;)

    start = time.time()
    for _ in range(iterations): solveoriginal(names)
    print(f&quot;Time taken for original function: {time.time() - start:.3f} s&quot;)

Here are the results
#                      Time taken 
#
#     iterations  |  original    |   new 
#   --------------------------------------
#       10 ** 6   |   2.553 s    |  2.106 s
#   --------------------------------------
#       11 ** 6   |   6.203 s    |  5.542 s
#   --------------------------------------
#       10 ** 7   |   32.412 s   |  24.774 s

Feel free to try it yourself