Beginner Issue; string index out of range - python

# word reverser
#user input word is printed backwards
word = input("please type a word")
#letters are to be added to "reverse" creating a new string each time
reverse = ""
#the index of the letter of the final letter of "word" the users' input
#use this to "steal" a letter each time
#index is the length of the word - 1 to give a valid index number
index = len(word) - 1
#steals a letter until word is empty, adding each letter to "reverse" each time (in reverse)
while word:
reverse += word[index]
word = word[:index]
print(reverse)
print(reverse)
input("press enter to exit")
Working to make a simple program that spells a user input word backwards and prints it back to them by "stealing" letters from the original and making new strings from them.
Trouble I'm having is this code spews back a string index out of range error at
reverse += word[index]
Help or a better way of achieving same result is mucho apreciado.

Reversing a word in python is simpler than that:
reversed = forward[::-1]
I wouldn't use a loop, it's longer and less readable.

While others have pointed out multiple ways of reversing words in Python, here is what I believe to be the problem with your code.
index always stay the same. Lets say the user inputs a four letter word, like abcd. Index will be set to three (index = len(word) - 1). Then during the first iteration of the loop, word will be reduced to abc (word = word[:index]). Then, during the next iteration of the loop, on the first line inside it (reverse += word[index]) you will get the error. index is still three, so you try to access index[3]. However, since word has been cut short there is no longer an index[3]. You need to reduce index by one each iteration:
while word:
reverse += word[index]
word = word[:index]
index -= 1
And here is yet another way of reversing a word in Python (Wills code is the neatest, though):
reverse = "".join([word[i-1] for i in range(len(word), 0, -1)])
Happy coding!

You're going to want to use the "range" function.
range(start, stop, step)
Returns a list from start to stop increasing (or decreasing) by step. Then you can iterate through the list. All together, it would look something like this:
for i in range(len(word) -1, -1, -1):
reverse += word[i]
print(reverse)
Or the easier way would be to use string slicing to reverse the word directly and then iterate through that. Like so:
for letter in word[::-1]:
reverse += letter
print(reverse)
With the way it is written now, it will not only print the word backwards, but it will also print each part of the backwards word. For example, if the user entered "Hello" it would print
o
ol
oll
olle
olleH
If you just want to print the word backwards, the best way is just
print(word[::-1])

It is because you are not changing the value of the index
modification:
while word:
reverse += word[index]
word = word[:index]
index-=1
print(reverse)`
that is you have to reduce index each time you loop through to get the current last letter of the word

Related

What is the difference between using range in the first program and not using it in the second program?

For an assignment, I needed to make a program that counts the vowels and consonants in a string using for i in range(0, len(str)):
I put this program together using what I learned, but I can't really wrap my head around why it works.
vowelCount = 0
consonantCount = 0
sentence = input("Enter your sentence: ")
for char in range(0, len(sentence)):
if sentence[char] in "aeiouAEIOU":
vowelCount += 1
if sentence[char] in "bcdfghjklmnpqrstvwxyBCDFGHJKLMNPQRSTVWXYZ":
consonantCount += 1
print("There are", vowelCount, "vowels")
print("There are", consonantCount, "consonants")
Why am I getting the range of the length of the sentence?
Here's an alternative program I wrote without the range.
vowelCount = 0
consonantCount = 0
sentence = input("Enter your sentence: ")
for i in sentence:
if i in "aeiouAEIOU":
vowelCount += 1
if i in "bcdfghjklmnpqrstvwxyBCDFGHJKLMNPQRSTVWXYZ":
consonantCount += 1
print("There are", vowelCount, "vowels")
print("There are", consonantCount, "consonants")
Why do I need to use sentence[char] in the range version? Why the brackets?
Your program is going through sentence one letter at a time. For each letter (retreived by sentence[char]) it checks whether it is in the list of vowels (if yes, increment vowelCount) or in the list of consonants (if yes, increment consonantCount).
The form a in b for strings a and b checks whether a is contained somewhere as exact substring in b. So if a is just a single letter, it checks whether b contains the letter a anywhere.
I suspect part of your confusion might arise because of the word "char." In the following code snippet, range(0, len(sentence)) generates numerical values. Thus, char is an index.
for char in range(0, len(sentence))
In other words, on the first iteration through the loop sentence[char] really looks something like sentence[0], or the first character in the sentence. If this character is in the string "aeiouAEIOU", the the boolean conditional in the loop returns TRUE
Note that if sentence[char] in "aeiouAEIOU" could be re-written like
if sentence[char] in set(['a','e','i','o','u','A','E','I','O','U'])
First: "aeiouAEIOU" is a string, which can also be seen as a List of characters in this context.
So ['a', 'e', 'i', 'o'....'U'] is equivalent to this string representation above.
Second: The in operator in python checks if the element on the left side is "in" the list on the right side. So for example
1 in [1,2,3] would return TRUE while 10 in [1,2,3] would return FALSE. Or for characters, 'o' in "Foobar" would return TRUE while 'c' in "Foobar" would return FALSE
The rest is just (pseudocode) IF ... THEN increase a number, so you basically loop through every character of a sentence and increase two variables if the character is in the list of vovels or in the list of consonants. After the loop is finished, you present the final counts.

Python index error for hangman game program

This is a piece of the program for a game of hangman. I am trying to iterate through the hangman word and print the letter guessed by the user if it matches at that index. If it does not it will print an underscore. I am getting the following error for the second if condition: IndexError: string index out of range
while(guessTracker >= 0):
letterGuess= input("Enter a letter for your guess: ")
count=0
wordGuess=""
if letterGuess in hangmanWord:
while count<= len(hangmanWord):
if hangmanWord[count]==letterGuess:
wordGuess= wordGuess+ letterGuess
right= right+1
else:
wordGuess= wordGuess + "_ "
count+=1
print(wordGuess)
In Python (and most other programming languages) string indexes start at 0 so the last position is len(hangmanWord)-1.
You can fix it just by changing <= to <.
Try
while count<= len(hangmanWord)-1:
Because the string's length will never reach the real length (for example: if the word is "hangman", it has a length of 7, but the count starts from 0, and goes up to a maximum of 6, therefor not being able to ever reach the 7th char.
String indexes are from 0 to len(string)-1;
you just need to change your loop like this:
while count < len(hangmanWord):
Indexes are 0-based so you index a string from index 0 up to len(hangmanWord) - 1.
hangmanWord[len(hangmanWord)] will always raise an IndexError.
You should also give a look to the enumerate function that can help with that.
wordGuess = ["_"] * len(hangmanWord)
for index, letter in enumerate(hangmanWord):
if letterGuess == letter:
wordGuess[index] = letter
print("".join(wordGuess))

Reverse a specific word function

I'm having trouble doing the next task:
So basically, I need to build a function that receives a (sentence, word, occurrence)
and it will search for that word and reverse it only where it occurs
for example:
function("Dani likes bananas, Dani also likes apples", "lik", "2")
returns: "Dani likes bananas, Dani also kiles apples"
As you can see, the "word" is 'lik' and at the second time it occurred it reversed to 'kil'.
I wrote something but it's too messy and that part still doesn't work for me,
def q2(sentence, word, occurrence):
count = 0
reSentence = ''
reWord = ''
for char in word:
if sentence.find(word) == -1:
print('could not find the word')
break
for letter in sentence:
if char == letter:
if word != reWord:
reWord += char
reSentence += letter
break
elif word == reWord:
if count == int(occurrence):
reWord = word[::-1]
reSentence += reWord
elif count > int(occurrence):
print("no such occurrence")
else:
count += 1
else:
reSentence += letter
print(reSentence)
sentence = 'Dani likes bananas, Dani also likes apples'
word = 'li'
occurrence = '2'
q2(sentence,word,occurrence)
the main problem right now is that, after it breaks it goes back to check from the start of the sentence so it will find i in "Dani". I couldn't think of a way to make it check from where it stopped.
I tried using enumerate but still had no idea how.
This will work for the given scenario
scentence = 'Dani likes bananas, Dani also likes apples'
word = 'lik'
st = word
occ = 2
lt = scentence.split(word)
op = ''
if (len(lt) > 1):
for i,x in enumerate(lt[:-1]):
if (i+1) == occ:
word = ''.join(reversed(word))
op = op + x + word
word = st
print(op+lt[-1])
Please test yourself for other scenario
This line for i,x in enumerate(lt[:-1]) basically loops on the list excluding the last element. using enumerate we can get index of the element in the list in i and value of element in x. So when code gets loops through it I re-join the split list with same word by which I broke, but I change the word on the specified position where you desired. The reason to exclude the last element while looping is because inside loop there is addition of word and after each list of element and if I include the whole list there will be extra word at the end. Hope it explains.
Your approach shows that you've clearly thought about the problem and are using the means you know well enough to solve it. However, your code has a few too many issue to simply fix, for example:
you only check for occurrence of the word once you're inside the loop;
you loop over the entire sentence for each letter in the word;
you only compare a character at a time, and make some mistakes in keeping track of how much you've matched so far.
you pass a string '2', which you intend to use as a number 2
All of that and other problems can be fixed, but you would do well to use what the language gives you. Your task breaks down into:
find the n-th occurrence of a substring in a string
replace it with another word where found and return the string
Note that you're not really looking for a 'word' per se, as your example shows you replacing only part of a word (i.e. 'lik') and a 'word' is commonly understood to mean a whole word between word boundaries.
def q2(sentence, word, occurrence):
# the first bit
position = 0
count = 0
while count < occurrence:
position = sentence.find(word, position+1)
count += 1
if position == -1:
print (f'Word "{word}" does not appear {occurrence} times in "{sentence}"')
return None
# and then using what was found for a result
return sentence[0:position] + word[::-1] + sentence[position+len(word):]
print(q2('Dani likes bananas, Dani also likes apples','lik',2))
print(q2('Dani likes bananas, Dani also likes apples','nope',2))
A bit of explanation on that return statement:
sentence[0:position] gets sentence from the start 0 to the character just before position, this is called a 'slice'
word[::-1] get word from start to end, but going in reverse -1. Leaving out the values in the slice implies 'from one end to the other'
sentence[position+len(word):] gets sentence from the position position + len(word), which is the character after the found word, until the end (no index, so taking everything).
All those combined is the result you need.
Note that the function returns None if it can't find the word the right number of times - that may not be what is needed in your case.
import re
from itertools import islice
s = "Dani likes bananas, Dani also likes apples"
t = "lik"
n = 2
x = re.finditer(t, s)
try:
i = next(islice(x, n - 1, n)).start()
except StopIteration:
i = -1
if i >= 0:
y = s[i: i + len(t)][::-1]
print(f"{s[:i]}{y}{s[i + len(t):]}")
else:
print(s)
Finds the 2nd starting index (if exists) using Regex. May require two passes in the worst case over string s, one to find the index, one to form the output. This can also be done in one pass using two pointers, but I'll leave that to you. From what I see, no one has offered a solution yet that does in one pass.
index = Find index of nth occurence
Use slice notation to get part you are interested in (you have it's beginning and length)
Reverse it
Construct your result string:
result = sentence[:index] + reversed part + sentence[index+len(word):]

Python - How to use string in index

Was wondering how you would use a string that is equal to an interger as the integer in an index.
word = input("Enter word:")
print(word)
letterNum = int(len(word)) #determines amount of letters in word
print(letterNum)
lastLetter = word[letterNum] #supposed to figure out the last letter in a word
print(lastLetter)
This will get you the last letter in a word without all the code. I'm unsure what you're asking by index though.
word = input("Enter word: ")
print(word[-1])
Example:
Enter word: Test
#"t"
If you're asking if "Test 1" was input and you want to get the last character as a number then it's as simple as wrapping it in int but do some checking first.
word = input("Enter word: ")
last_char = word[-1]
if isnumeric(word[-1]):
print(int(last_char))
else:
print(last_char)
Examples:
Enter word: Test 1
#1
Enter word: Test
#"t"
The simplest way with python is to index using -1. Negative indexes count from the end of the string so word[-1] will always give you the last letter
Here I am giving you few of the examples including above.
word = input("Enter word:").strip() # strip() is used to remove any trailing or leading white spaces
print(word)
letterNum = int(len(word)) # Determines amount of letters in word
print(letterNum)
# 1st way (Using the internet that we created above)
lastLetter = word[letterNum - 1] # Supposed to figure out the last letter in a word
print(lastLetter)
# 2nd way (As the above answers suggest, -ve index, -1 for last, -2 for 2nd last, this is best, but this basically for Python, other language like C/C++ etc. use 1st way)
print(word[-1])
# 3rd way (Not good, but it is good for those who are learning Python,Reversing the string and printing 1st character)
print(word[::-1][0])

how to reverse a sentence with a while loop

For an assignment, I need to use a while loop to reverse a list, and I just can't do it.
This is the sample code I have to help me get started:
sentence = raw_int (" ")
length = len(sentence) # determines the length of the sentence (how many characters there are)
index = length - 1 #subtracts one from the length because we will be using indexes which start at zero rather than 1 like len
while... #while the index is greater than or equal to zero continue the loop
letter = sentence[index] #take the number from the index in the sentence and assigns it to the variable letter
I need to use this in my solution.
sentence = raw_input(" ")
length = len(sentence)
index = length - 1
reversed_sentence = ''
while index >= 0:
#letter is the last letter of the original sentence
letter = sentence[index]
#make the first letter of the new sentence the last letter of the old sentence
reversed_sentence += letter
#update the index so it now points to the second to last letter of the original sentence
index = index - 1
print reversed_sentence
Because this is an assignment, I'm not going to give you the full code. But I will give you two 'hints'.
1) a sentenced is reversed if every character is 'flipped'. For example, 'I ran fast'-to flip this sentence first swap 'I' and 'f', then space and 's' and so on.
2) you can use syntax like:
Sentence[i], sentence[len(sentence)-i] = sentence[len(sentence)-i], Sentence[i]
This should definitely be enough to get you going.
You can do:
new_sentence = list()
sentence = list(raw_input(" "))
while sentence:
new_sentence.append(sentence.pop(-1))
else:
sentence = ''.join(new_sentence)

Categories

Resources