String Index Out of Range when comparing characters - python

I am simply trying to compare one character in a string to its neighbor, but I keep getting a string index out of range error. I can't figure this out.
s = 'azcbobobegghakl'
current = ""
previous = ""
for letter in range(0,len(s)):
if s[letter] <= s[letter+1]:
current += s[letter]
print(current)
Thanks

The if statement was unnecessary. On the last iteration of the loop, s[letter+1] was throwing an error because that index of the string didn't exist. At that point, letter was equal to the length of your string, s. letter+1 was one higher than the length, so the index didn't exist.
There is no need to compare the value of letter to the length of s in the if statement because the loop would end before letter is greater than the length of s.
Solution:
s = 'azcbobobegghakl'
current = ""
previous = ""
for letter in range(0,len(s)):
current += s[letter]
print(current)

while #sedavidw is completely right pointing out the indexing issue, it is not a very pythonic way of doing such a comparison. I'd do something like:
current = ''.join(letter for letter, next_letter in zip(s, s[1:])
if letter <= next_letter)

I think you want to print a letter only if the previous one is less than the current one. The index out of bounds occur because the last index points to (l) but index + 1 points to nothing.
Here is my solution:
s = 'azcbobobegghakl'
current = ""
previous = ""
for letter in range(0,len(s)):
if letter + 1 < len(s): # this is important to prevent the index out of bounds error
if s[letter] <= s[letter+1]:
current += s[letter]
print(current)
Output: abbbeggak

Related

What is wrong with my code trying to find longest substring of a string that is in alphabetical order?

I need help on a problem that I am doing in a course. The exact details are below:
Assume s is a string of lower case characters.
Write a program that prints the longest substring of s in which the letters occur in alphabetical order.
For example, if s = 'azcbobobegghakl', then your program should print
"Longest substring in alphabetical order is: beggh"
In the case of ties, print the first substring. For example, if s = 'abcbcd', then your program should print
"Longest substring in alphabetical order is: abc"
I have written some code that achieves some correct answers but not all and I am unsure why.
This is my code
s = 'vettmlxvn'
alphabet = "abcdefghijklmnopqrstuvwxyz"
substring = ""
highest_len = 0
highest_string = ""
counter = 0
for letter in s:
counter += 1
if s.index(letter) == 0:
substring = substring + letter
highest_len = len(substring)
highest_string = substring
else:
x = alphabet.index(substring[-1])
y = alphabet.index(letter)
if y >= x:
substring = substring + letter
if counter == len(s) and len(substring) > highest_len:
highest_len = len(substring)
highest_string = substring
else:
if len(substring) > highest_len:
highest_len = len(substring)
highest_string = substring
substring = "" + letter
else:
substring = "" + letter
print("Longest substring in alphabetical order is: " + highest_string)
When I test for this specific string it gives me "lxv" instead of the correct answer: "ett". I do not know why this is and have even tried drawing a trace table so I can trace variables and I should be getting "ett".
Maybe I have missed something simple but can someone explain why it is not working.
I know there are probably easier ways to do this problem but I am a beginner in python and have been working on this problem for a long time.
Just want to know what is wrong with my code.
Thanks.
I solved your Problem with an alternate simpler approach.
You can compare 2 characters like numbers. a comes before b in the alphabet, that means the expression 'a' < 'b' is True
def longest_substring(s):
# Initialize the longest substring
longest = ""
# Initialize the current substring
current = ""
# Loop through the string
for i in range(len(s)):
if i == 0:
# If it's the first letter, add it to the current substring
current += s[i]
else:
if s[i] >= s[i-1]:
# If the current letter is greater than or equal to the previous letter,
# add it to the current substring
current += s[i]
else:
# If the current letter is less than the previous letter,
# check if the current substring is longer than the longest substring
# and update the longest substring if it is
if len(current) > len(longest):
longest = current
current = s[i]
# Once the loop is done,
# check again if the current substring is longer than the longest substring
if len(current) > len(longest):
longest = current
return longest
print(longest_substring("azcbobobegghakl"))
print(longest_substring("abcbcd"))
print(longest_substring("abcdefghijklmnopqrstuvwxyz"))
print(longest_substring("vettmlxvn"))
Output:
beggh
abc
abcdefghijklmnopqrstuvwxyz
ett
I haven't figured out what's wrong with your code yet. I will update this if I figured it out.
Edit
So commented some stuff out and changed one thing.
Here's the working code:
s = 'vettmlxvn'
alphabet = "abcdefghijklmnopqrstuvwxyz"
substring = ""
highest_len = 0
highest_string = ""
counter = 0
for letter in s:
counter += 1
if s.index(letter) == 0:
substring = substring + letter
# highest_len = len(substring)
# highest_string = substring
else:
x = alphabet.index(substring[-1])
y = alphabet.index(letter)
if y >= x:
substring = substring + letter
if counter == len(s) and len(substring) > highest_len:
highest_len = len(substring)
highest_string = substring
else:
if len(substring) > len(highest_string): # changed highest_len to len(highest_string)
#highest_len = len(substring)
highest_string = substring
substring = "" + letter
else:
substring = "" + letter
print("Longest substring in alphabetical order is: " + highest_string)
You are overwriting highest_string at the wrong time. Only overwrite it if the substrings ends and after checking if it's greater than the longest found before.
Outputs:
Longest substring in alphabetical order is: ett
Alternate Approach
Break input string into substrings
Where each substring is increasing
Find the longest substring
Code
def longest_increasing_substring(s):
# Break s into substrings which are increasing
incr_subs = []
for c in s:
if not incr_subs or incr_subs[-1][-1] > c:# check alphabetical order of last letter of current
# string to current letter
incr_subs.append('') # Start new last substring since not in order
incr_subs[-1] += c # append to last substsring
return max(incr_subs, key = len) # substring with max length
Test
for s in ['vettmlxvn', 'azcbobobegghakl', 'abcbcd']:
print(f'{s} -> {longest_increasing_substring(s)}')
Output
vettmlxvn -> ett
azcbobobegghakl -> beggh
abcbcd -> abc

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))

I want to create a program that finds the longest substring in alphabetical order using python using basics

my code for finding longest substring in alphabetical order using python
what I mean by longest substring in alphabetical order?
if the input was"asdefvbrrfqrstuvwxffvd" the output wil be "qrstuvwx"
#we well use the strings as arrays so don't be confused
s='abcbcd'
#give spaces which will be our deadlines
h=s+' (many spaces) '
#creat outputs
g=''
g2=''
#list of alphapets
abc='abcdefghijklmnopqrstuvwxyz'
#create the location of x"the character the we examine" and its limit
limit=len(s)
#start from 1 becouse we substract one in the rest of the code
x=1
while (x<limit):
#y is the curser that we will move the abc array on it
y=0
#putting our break condition first
if ((h[x]==' ') or (h[x-1]==' ')):
break
for y in range(0,26):
#for the second character x=1
if ((h[x]==abc[y]) and (h[x-1]==abc[y-1]) and (x==1)):
g=g+abc[y-1]+abc[y]
x+=1
#for the third to the last character x>1
if ((h[x]==abc[y]) and (h[x-1]==abc[y-1]) and (x!=1)):
g=g+abc[y]
x+=1
if (h[x]==' '):
break
print ("Longest substring in alphabetical order is:" +g )
it doesn't end,as if it's in infinite loop
what should I do?
I am a beginner so I want some with for loops not functions from libraries
Thanks in advance
To avoid infinite loop add x += 1 in the very end of your while-loop. As a result your code works but works wrong in general case.
The reason why it works wrong is that you use only one variable g to store the result. Use at least two variables to compare previous found substring and new found substring or use list to remember all substrings and then choose the longest one.
s = 'abcbcdiawuhdawpdijsamksndaadhlmwmdnaowdihasoooandalw'
longest = ''
current = ''
for idx, item in enumerate(s):
if idx == 0 or item > s[idx-1]:
current = current + item
if idx > 0 and item <= s[idx-1]:
current = ''
if len(current)>len(longest):
longest = current
print(longest)
Output:
dhlmw
For your understanding 'b'>'a' is True, 'a'>'b' is False etc
Edit:
For longest consecutive substring:
s = 'asdefvbrrfqrstuvwxffvd'
abc = 'abcdefghijklmnopqrstuvwxyz'
longest = ''
current = ''
for idx, item in enumerate(s):
if idx == 0 or abc.index(item) - abc.index(s[idx-1]) == 1:
current = current + item
else:
current = item
if len(current)>len(longest):
longest = current
print(longest)
Output:
qrstuvwx
def sub_strings(string):
substring = ''
string +='\n'
i = 0
string_dict ={}
while i < len(string)-1:
substring += string[i]
if ord(substring[-1])+1 != ord(string[i+1]):
string_dict[substring] = len(substring)
substring = ''
i+=1
return string_dict
s='abcbcd'
sub_strings(s)
{'abc': 3, 'bcd': 3}
To find the longest you can domax(sub_strings(s))
So here which one do you want to be taken as the longest??. Now that is a problem you would need to solve
You can iterate through the string and keep comparing to the last character and append to the potentially longest string if the current character is greater than the last character by one ordinal number:
def longest_substring(s):
last = None
current = longest = ''
for c in s:
if not last or ord(c) - ord(last) == 1:
current += c
else:
if len(current) > len(longest):
longest = current
current = c
last = c
if len(current) > len(longest):
longest = current
return longest
so that:
print(longest_substring('asdefvbrrfqrstuvwxffvd'))
would output:
qrstuvwx

Is it possible to achieve this without defining a function?

I'm trying to write a Python program which would take a string and print the longest substring in it which is also in alphabetical order. For example:
the_string = "abcdefgghhisdghlqjwnmonty"
The longest substring in alphabetical order here would be "abcdefgghhis"
I'm not allowed to define my own functions and can't use lists. So here's what I came up with:
def in_alphabetical_order(string):
for letter in range(len(string) - 1):
if string[letter] > string[letter + 1]:
return False
return True
s = "somestring"
count = 0
for char in range(len(s)):
i = 0
while i <= len(s):
sub_string = s[char : i]
if (len(sub_string) > count) and (in_alphabetical_order(sub_string)):
count = len(sub_string)
longest_string = sub_string
i += 1
print("Longest substring in alphabetical order is: " + longest_string)
This obviously contains a function that is not built-in. How can I check whether the elements of the substring candidate is in alphabetical order without defining this function? In other words: How can I implement what this function does for me into the code (e.g. by using another for loop in the code somewhere or something)?
just going by your code you can move the operation of the function into the loop and use a variable to store what would have been the return value.
I would recommend listening to bill the lizard to help with the way you solve the problem
s = "somestring"
count = 0
longest_string = ''
for char in range(len(s)):
i = 0
while i <= len(s):
sub_string = s[char : i]
in_order = True
for letter in range(len(sub_string) - 1):
if sub_string[letter] > sub_string[letter + 1]:
in_order = False
break
if (len(sub_string) > count) and (in_order):
count = len(sub_string)
longest_string = sub_string
i += 1
print("Longest substring in alphabetical order is: " + longest_string)
You don't need to check the whole substring with a function call to see if it is alphabetical. You can just check one character at a time.
Start at the first character. If the next character is later in the alphabet, keep moving along in the string. When you reach a character that's earlier in the alphabet than the previous character, you've found the longest increasing substring starting at the first character. Save it and start over from the second character.
Each time you find the longest substring starting at character N, check to see if it is longer than the previous longest substring. If it is, replace the old one.
Here's a solution based off of what you had:
s = 'abcdefgghhisdghlqjwnmonty'
m, n = '', ''
for i in range(len(s) - 1):
if s[i + 1] < s[i]:
if len(n) > len(m):
m = n
n = s[i]
else:
n += s[i]
Output:
m
'abcdefgghhi'

Python Range Error in While Loop

I am trying to write a python program that will take any string of lowercase letters and return the longest alphabetical substring within it. Below is a segment of the code.
s="abc" #sample string
anslist=[] #stores answers
shift=0 #shifts substring
expan=0 #expands substring
while len(s) >= 1+shift+expan: #within bounds of s
if s[0+shift+expan] > s[1+shift+expan]: #if not alphabetical
shift += 1 #moves substring over
else: #if alphabetical
while s[0+shift+expan] <= s[1+shift+expan]: #while alphabetical
expan += 1 #checks next letter
anslist += s[0+shift:2+shift+expan] #adds substring to ans
expan = 0 #resets expansion
When I run the code, the line containing
while s[0+shift+expan] <= s[1+shift+expan]:
creates an error that the string index is outside of the range. I see that adding to expan will put the index out of range, but shouldn't the largest while loop solve this? I appreciate any help.
First, why your code doesn't work:
You aren't protecting your inner loop against running off the end of the string
your indexes are off when "saving" the substring
you += onto anslist, which is not how you add strings to a list
you don't increment the shift after processing a substring, so when it clears expan it starts over at the same index and loops forever
Fixed code (inline comments explain changes):
s="abckdefghacbde" #sample string
anslist=[] #stores answers
shift=0 #shifts substring
expan=0 #expands substring
while len(s) > 1+shift+expan: #within bounds of s
if s[0+shift+expan] > s[1+shift+expan]: #if not alphabetical
shift += 1 #moves substring over
else: #if alphabetical
# Added guard for end of string
while len(s) > 1 + shift + expan and # While still valid
s[0+shift+expan] <= s[1+shift+expan]:# While alphabetical
expan += 1 #checks next letter
# Fixed string sublength and append instead of +=
anslist.append(s[0+shift:1+shift+expan]) #adds substring to ans
# Continue to next possible substring
shift += expan # skip inner substrings
expan = 0
print anslist
Results in:
['abck', 'defgh', 'ac', 'bde']
So the last step would be to find the one with the longest length, which I'll leave up to you, since this looks like homework.
To answer the question:
I see that adding to expan will put the index out of range, but shouldn't the largest while loop solve this?
It protects against your starting substring index from going off, but not your expansion. You must protect against both possibilities.
Have a look at this.
>>> import re
>>> words = []
>>> word = r'[a]*[b]*[c]*[d]*[e]*[f]*[g]*[h]*[i]*[j]*[k]*[l]*[m]*[n]*[o]*[q]*[r]*[s]*[t]*[u]*[v]*[x]*[y]*[z]*' # regex that would match sub-strings. Just extend it up to z.
>>> string = "bacde"
>>> for m in re.finditer(word, string):
... words.append(m.group())
>>> print(words) # list of substrings
['b', 'acde']
Then you can extract the largest string from the list of strings
>>> print(max(words, key=len))
acde

Categories

Resources