Getting a 'list index out of range' error - python

The goal of this code is to find the number of 'sh', 'th', 'wh', and 'ch' digraphs there are in any given sentence. The function keeps returning a 'list index out of range' error, when it seems like everything should be running properly.
exsentence = input("Enter a sentence to scan: ")
slist = list(exsentence.lower())
ch = 0
sh = 0
th = 0
wh = 0
i = 0
'''muppets = slist[i] + slist[i+1]'''
while i < len(slist):
if slist[i] + slist[i+1] == "sh":
sh += 1
elif slist[i] + slist[i+1] == "ch":
ch += 1
elif slist[i] + slist[i+1] == "th":
th += 1
else:
if slist[i] + slist[i+1] == "wh":
wh += 1
i+=1
print("Has {} 'ch' {} 'sh' {} 'th' {} 'wh'".format(ch,sh,th,wh))
Any help is very appriceciated. Thank you.

i+1 will be out of slist bounds. You need to iterate until slist size - 1
while i < len(slist) - 1:
As a side note, for seems to be more appropriate here. Remove i = 0 and i+=1
for i in range(len(slist) - 1):

Use a for loop with range instead:
exsentence = input("Enter a sentence to scan: ")
slist = list(exsentence.lower())
ch = 0
sh = 0
th = 0
wh = 0
i = 0
'''muppets = slist[i] + slist[i+1]'''
for i in range(1,len(slist)):
if slist[i-1] + slist[i] == "sh":
sh += 1
elif slist[i-1] + slist[i] == "ch":
ch += 1
elif slist[i-1] + slist[i] == "th":
th += 1
elif slist[i-1] + slist[i] == "wh":
wh += 1
print(f"Has {ch} 'ch' {sh} 'sh' {th} 'th' {wh} 'wh'")
start the range at 1 and check i-1 against i this way you wont go out of index range

You are checking one position ahead of the current one. Thus you are getting the error of being out of range.
Basically, you are iterating over each position of the array, but you are checking for the nth position against the nth + 1 position. What does happen when you reach the last position? You check it with the next position, which is not defined (otherwise it would not be the last position), and thus get the out of range error.
My suggestion is to not perform the check on the last item against the next one, as there will not be any sequence anymore.
while i < len(slist) - 1:
if slist[i] + slist[i+1] == "sh":
sh += 1
elif slist[i] + slist[i+1] == "ch":
ch += 1
elif slist[i] + slist[i+1] == "th":
th += 1
else:
if slist[i] + slist[i+1] == "wh":
wh += 1
i+=1

Related

Adding if condition based on value [Python]

So basically, I have to add one more condition to my if statement depending on the length of the list. Here's the sample code:
for index in indices:
if len(phrase.split(" ")) == 1:
if path in rang:
rang[path] += 1
else:
rang[path] = 1
elif len(phrase.split(" ")) == 2:
if phrase.split(" ")[1] == parser.words[index + 1]:
if path in rang:
rang[path] += 1
else:
rang[path] = 1
elif len(phrase.split(" ")) == 3:
if phrase.split(" ")[1] == parser.words[index + 1] and phrase.split(" ")[2] == parser.words[index + 2]:
if path in rang:
rang[path] += 1
else:
rang[path] = 1
else:
if phrase.split(" ")[1] == parser.words[index + 1] and phrase.split(" ")[2] == parser.words[index + 2] and phrase.split(" ")[3] == parser.words[index + 3]:
if path in rang:
rang[path] += 1
else:
rang[path] = 1
So basically you are trying this?
all(p==q for p, q in zip(phrase.split(" ")[1:], parser.words[index+1:]))
That should replace all the if/elif-statements.
zip returns a tuple of two elements, one from each list; we are then iterating this list of tuples and checking for equality of both elements; just like in your code, but without knowing/restricting about the length of the lists
You can replace your code by:
for index in indices:
if len(phrase.split(" "))==1 or all(p==q for p, q in zip(phrase.split(" ")[1:], parser.words[index+1:])):
if path in rang:
rang[path] += 1
else:
rang[path] = 1

What is wrong with my nested while loop for counting the element

I just want to figure out how often each element of F occurs within N and print it out. I have used the nested for loop, it works. But when I used nested while loop, it did not work as expected. I checked my code but cannot find out why.
F = [4,7,2]
N = [2,3,4,2,5,6,3,2,6,7,3,4]
Nested for loop version, works as expected:
four_count = 0
seven_count = 0
two_count = 0
for n in N:
for f in F:
if n == f and f == 4:
four_count += 1
elif n == f and f == 7:
seven_count += 1
elif n == f and f == 2:
two_count += 1
print(str(F[0]) + " occurs in N " + str(four_count) + " times")
print(str(F[1]) + " occurs in N " + str(seven_count) + " times")
print(str(F[2]) + " occurs in N " + str(two_count) + " times")
This is correct output:
4 occurs in N 2 times
7 occurs in N 1 times
2 occurs in N 3 times
Nested while loop version, wrong output:
four_count = 0
seven_count = 0
two_count = 0
N_Count = 0
F_Count = 0
while N_Count < len(N):
while F_Count < len(F):
if N[N_Count] == F[F_Count] and F[F_Count] == 4:
four_count += 1
elif N[N_Count] == F[F_Count] and F[F_Count] == 7:
seven_count += 1
elif N[N_Count] == F[F_Count] and F[F_Count] == 2:
two_count += 1
F_Count += 1
N_Count += 1
print(str(F[0]) + " occurs in N " + str(four_count) + " times")
print(str(F[1]) + " occurs in N " + str(seven_count) + " times")
print(str(F[2]) + " occurs in N " + str(two_count) + " times")
Wrong output from nested while loop:
4 occurs in N 0 times
7 occurs in N 0 times
2 occurs in N 1 times
You have to reset F_Count = 0 after while N_Count < len(N):, otherwise list F is only looped once. So it would be:
...
while N_Count < len(N):
F_Count = 0
while F_Count < len(F):
...
But unless you're learning about loops, this would not be the best way to do what you want. Something using count would be better, like:
counts = [N.count(f) for f in F]
or similar

list index out of range python 3.6

List index out of range error occurs at the line
if large_l[lg_index] ==small_l[sl_index]:
Here the code works fine when the values of following are,
correctword = "syria"
incorrectword = "siria"
but when assigning value as follows,
correctword = "syria"
incorrectword = "syri"
the above mentioned error has occurred. If could, tell me a way to get rid from this error.
Thank you
correctword = "syria"
incorrectword = "syri"
l1 = list(correctword)
l2 = list(incorrectword)
if len(l1) < len(l2):
large_l= l2
small_l = l1
else:
large_l =l1
small_l = l2
missmatchstart = False
lg_mismatch_start_index = 0
sl_mismatch_start_index = 0
lg_index = 0
sl_index = 0
del_count=0
add_count = 0
sub_count = 0
for l1_item in large_l:
for l2_item in small_l:
if large_l[lg_index] ==small_l[sl_index]:
if missmatchstart == False:
sl_mismatch_start_index = sl_index
lg_mismatch_start_index = lg_index
print(large_l[lg_index])
print("addition ")
print(add_count)
print("deletion ")
print(del_count)
print("substitution ")
print(sub_count)
if lg_index-lg_mismatch_start_index == sl_index-sl_mismatch_start_index:
sub_count += sl_index-sl_mismatch_start_index
lg_index+= 1
sl_index+= 1
elif lg_index-lg_mismatch_start_index > sl_index-sl_mismatch_start_index:
sub_count += sl_index-sl_mismatch_start_index
del_count += ((lg_index-lg_mismatch_start_index) - (sl_index-sl_mismatch_start_index))
lg_index+= 1
sl_index+= 1
elif lg_index-lg_mismatch_start_index < sl_index-sl_mismatch_start_index:
sub_count += lg_index-lg_mismatch_start_index
add_count += ((sl_index-sl_mismatch_start_index) - (lg_index-lg_mismatch_start_index))
lg_index+= 1
sl_index+= 1
missmatchstart = False
break
else:
print(large_l[lg_index])
if(missmatchstart == False):
lg_mismatch_start_index = lg_index
sl_mismatch_start_index = sl_index
print("missmatch large")
print(lg_mismatch_start_index)
print("missmatch small")
print(sl_mismatch_start_index)
missmatchstart =True
sl_index+=1
else:
sl_index+=1
if sl_index== len(small_l)-1:
lg_index +=1
sl_index = sl_mismatch_start_index
#del_count +=1
break
# elif lg_index == sl_index == len(small_l):
# sub_count +=
if lg_index >=len(large_l)-1:
del_count += len(large_l)- lg_index
#elif missmatchstart ==True:
print(add_count)
print(del_count)
print(sub_count)
You probably want to replace the condition on line 24:
if large_l[lg_index] ==small_l[sl_index]:
with:
if l1_item == l2_item:
There might be other bugs there, you should make your code more modular by splitting it into functions (in a reasonable matter) - it will be easier to maintain and debug!

Counting while using recursion with strings from inputs

I'm trying to create a game where the score is dependent on what the letters are worth. I'm having trouble with keeping a count on the side while still recursing to the next letter of the string. I'm really stuck & I hope you can help!
def net_zero():
guess_prompt = input('Guess a string: ')
win_display = 'Congratulations you win'
low_vowels = "aeiou" # +1
low_constants = "bcdfghjklmnpqrstvwxyz" # -1
up_vowels = "AEIOU" # +2
up_constants = "BCDFGHJKLMNPQRSTVWXYZ" # -2
ten_digits = "0123456789" # +3
#else -3
count = 0
if len(guess_prompt) == 0:
return count
elif guess_prompt[0] in low_vowels:
return (count + 1) + guess_prompt[1:]
elif guess_prompt[0] in low_constants:
return (count - 1) + guess_prompt[1:]
elif guess_prompt[0] in up_vowels:
return (count + 2) + guess_prompt[1:]
elif guess_prompt[0] in up_constants:
return (count - 2) + guess_prompt[1:]
elif guess_prompt[0] in ten_digits:
return (count + 3) + guess_prompt[1:]
else: return (count - 3) + guess_prompt[1:]
I think you would like to do following
count = 0
if len(guess_prompt) == 0:
return count
for letter in guess_prompt:
if letter in low_vowels:
count +=1
if letter in low_constants:
count -=1
...
return count
I feel you can use dict instead of using string content for lookup. It will improve lookup time.
guess_prompt = "aaB4??BBBBB"
value = {}
for char in "aeiou":
value[char] = 1
for char in "bcdfghjklmnpqrstvwxyz":
value[char] = -1
for char in "AEIOU":
value[char] = 2
for char in "BCDFGHJKLMNPQRSTVWXYZ":
value[char] = -2
for char in "0123456789":
value[char] = 3
count = 0
for char in guess_prompt:
count = count + value.get(char, -3) #default value -3
print(count) ## PRINTS -13 ##

How do I run a binary search for words that start with a certain letter?

I am asked to binary search a list of names and if these names start with a particular letter, for example A, then I am to print that name.
I can complete this task by doing much more simple code such as
for i in list:
if i[0] == "A":
print(i)
but instead I am asked to use a binary search and I'm struggling to understand the process behind it. We are given base code which can output the position a given string. My problem is not knowing what to edit so that I can achieve the desired outcome
name_list = ["Adolphus of Helborne", "Aldric Foxe", "Amanita Maleficant", "Aphra the Vicious", "Arachne the Gruesome", "Astarte Hellebore", "Brutus the Gruesome", "Cain of Avernus"]
def bin_search(list, item):
low_b = 0
up_b = len(list) - 1
found = False
while low_b <= up_b and found == False:
midPos = ((low_b + up_b) // 2)
if list[midPos] < item:
low_b = midPos + 1
elif list[midPos] > item:
up_b = midPos - 1
else:
found = True
if found:
print("The name is at positon " + str(midPos))
return midPos
else:
print("The name was not in the list.")
Desired outcome
bin_search(name_list,"A")
Prints all the names starting with A (Adolphus of HelBorne, Aldric Foxe .... etc)
EDIT:
I was just doing some guess and check and found out how to do it. This is the solution code
def bin_search(list, item):
low_b = 0
up_b = len(list) - 1
true_list = []
count = 100
while low_b <= up_b and count > 0:
midPos = ((low_b + up_b) // 2)
if list[midPos][0] == item:
true_list.append(list[midPos])
list.remove(list[midPos])
count -= 1
elif list[midPos] < item:
low_b = midPos + 1
count -= 1
else:
up_b = midPos - 1
count -= 1
print(true_list)
Not too sure if this is what you want as it seems inefficient... as you mention it seems a lot more intuitive to just iterate over the entire list but using binary search i found here i have:
def binary_search(seq, t):
min = 0
max = len(seq) - 1
while True:
if max < min:
return -1
m = (min + max) // 2
if seq[m][0] < t:
min = m + 1
elif seq[m][0] > t:
max = m - 1
else:
return m
index=0
while True:
index=binary_search(name_list,"A")
if index!=-1:
print(name_list[index])
else:
break
del name_list[index]
Output i get:
Aphra the Vicious
Arachne the Gruesome
Amanita Maleficant
Astarte Hellebore
Aldric Foxe
Adolphus of Helborne
You just need to found one item starting with the letter, then you need to identify the range. This approach should be fast and memory efficient.
def binary_search(list,item):
low_b = 0
up_b = len(list) - 1
found = False
midPos = ((low_b + up_b) // 2)
if list[low_b][0]==item:
midPos=low_b
found=True
elif list[up_b][0]==item:
midPos = up_b
found=True
while True:
if found:
break;
if list[low_b][0]>item:
break
if list[up_b][0]<item:
break
if up_b<low_b:
break;
midPos = ((low_b + up_b) // 2)
if list[midPos][0] < item:
low_b = midPos + 1
elif list[midPos] > item:
up_b = midPos - 1
else:
found = True
break
if found:
while True:
if midPos>0:
if list[midPos][0]==item:
midPos=midPos-1
continue
break;
while True:
if midPos<len(list):
if list[midPos][0]==item:
print list[midPos]
midPos=midPos+1
continue
break
else:
print("The name was not in the list.")
the output is
>>> binary_search(name_list,"A")
Adolphus of Helborne
Aldric Foxe
Amanita Maleficant
Aphra the Vicious
Arachne the Gruesome
Astarte Hellebore

Categories

Resources