3
\$\begingroup\$

I have written an answer to this question on Stack Overflow. To make it easier for you, I have copy-pasted the question below.

Your friend wants to try to make a word ladder! This is a list of words where each word has a one-letter difference from the word before it.

Here’s an example:

cat
cot
cog
log

Write a program to help your friend. It should do the following:

  • Ask your friend for an initial word.

  • Repeatedly ask them for an index and a letter.

  • You should replace the letter at the index they provided with the letter they enter.

  • You should then print out the new word.

  • Stop asking for input when the user enters -1 for the index.

My answer to this is:

import os
get_index = 0
word = input("Enter a word: ")
for i in range(len(word)):
    while True:
        try:
            get_index = int(input("Enter an index (-1 to quit): "))
            if get_index == -1:
                os._exit(0)
            elif get_index < -1 or get_index > 2:
                raise ValueError
        except ValueError:
            print ("Invalid index!")
        else:
            while True:
                try:    
                    letter = input("Enter a letter: ")
                    for c in letter:
                        if c.isupper():
                            raise ValueError
                except ValueError:
                    print ("Character must be a lowercase letter!")
                else:
                    if len(letter) > 1:
                        print ("Must be exactly one character!")
                    else:
                        word = word[:get_index] + letter + word[get_index + 1:]
                        print (word)
                        break

NOTE #1: Here is a link to the program run (output): OUTPUT

NOTE #2: I would also like to use an alternative for os._exit() as it takes time for the program to completely end.

So, I would like to know whether I could make this code shorter and more efficient.

Any help would be highly appreciated.

\$\endgroup\$
2
\$\begingroup\$

While your code seems to work, the next step should be separating the different responsibilities of your code. As far as I can see, there are three:

  • You have to ask the user for an index. It needs to be an integer in the range [-1, len(s)).
  • You have to ask them for a replacement character. It must be exactly one lower case character.
  • You need to actually run the game.

The first two can be combined into a general function asking the user for input with type and validation:

def ask_user(message, type_=str, valid=lambda: True, invalid="Invalid"):
    while True:
        try:
            user_input = type_(input(message))
        except ValueError:
            print(invalid)
            continue
        if not valid(user_input):
            print(invalid)
            continue
        return user_input

And your main program can then use this function. I would also change the internal data of the word to be a list, so you can easily replace characters. When printing the word, just use "".join(word).

def play_word_ladder():
    word = list(input("Enter a word: "))

    def valid_index(i):
        return i in range(-1, len(word))

    def valid_character(c):
        return len(c) == 1 and c.islower()

    while True:
        index = ask_user("Enter an index (-1 to quit): ",
                         int, valid_index, "Invalid index!")
        if index == -1:
            return
        char = ask_user("Enter a letter: ", str, valid_character,
                        "Character must be one lowercase letter!")
        word[index] = char
        print("".join(word))

Note that your outer for loop is completely unnecessary.

The game can be started under a if __name__ == "__main__": guard to allow importing from this script. Note that you don't need to manually exit the script, it will do so automatically at the end.

if __name__ == "__main__":
    play_word_ladder()
\$\endgroup\$
  • 1
    \$\begingroup\$ Upvoted! I tested it and it worked perfectly. Definitely more efficiently than my code above :) \$\endgroup\$ – Justin May 12 at 12:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.