I am having trouble with this python programme [duplicate] - python

This question already has answers here:
How can I iterate over overlapping (current, next) pairs of values from a list?
(12 answers)
Closed 6 months ago.
I am a beginner and am trying to write a piece of code that tells you how long the longest substring is that is written in alphabetic order.
So far I have:
s = 'azcbobobegghakl'
n=len(s)
i=0
longest=1
while i<n+1:
print(s[i])
if s[i] < s[i+1]:
longest+=1
i+=1
else:
i+=1
print(longest)
However I keep getting an error:
IndexError: string index out of range
Could somebody please tell me where I am going wrong and how to fix it

Try this:
s = 'azcbobobegghakl'
n=len(s)
longest=1
counter=1
for i in range(len(s)-1):
print(s[i])
if s[i] < s[i+1]:
counter+=1
else:
if counter > longest:
longest = counter
counter = 1
if counter > longest:
longest = counter
print(longest)

Change your condition in while loop like this
Change
while i < n-1:
Change n+1 to n-1
Reason:
n is length of string
Index of string : 0,1,.....,n-1
In your program one iteration will check next element also:
ie: when I == 0 , it will access str[0], str[1]
Like i == n - 2 , str[n-2], str[n-1]
Now if your condition is i less than n +1 then it will check
i == n , str[n], str[n+1] it will give you index out of range
because str[n+1] doesn't exist

Error that you are getting is IndexError: string index out of range in line 11 if s[i] < s[i+1]:. The problem is that i in while loop will become too big (bigger than n-1). Your loop condition should be while i<n-1: and NOT while i<n-1: like others have suggested in their answers. You are checking for each character in string s if it is smaller (if it appears before in alphabet, actually, Python check if it has a smaller Unicode code, so you need to use only lowercase or only uppercase letters) than the next character in the string. And you can check this for all characters in a string except the last one because the last character doesn't have successor (there is no next character after last one). That's why you should have i<n-1: in your while loop.
Full working code:
s = 'azcbobobegghakl'
n=len(s)
i=0
longest=1
print(n)
while i<n-1:
print(s[i])
if s[i] < s[i+1]:
longest+=1
i+=1
else:
i+=1
print(longest)

try this:
s = 'azcbobobegghakl'
n=len(s)
i=0
longest=1
while i<n:
print(s[i])
if i == n-1:
break
elif s[i] < s[i+1]:
longest+=1
i+=1
else:
i+=1
print(longest)

Related

To Remove consecutive vowels from string

Here I want to remove any vowels which repeat consecutively. But it shows error as "list out of index".
So I tried break if last element in list is reached, but still won't work.
Here is the code I tried:-
a=[]
b=str(input("enter the string"))
a=b.split(',')
c=['a','e','i','o','u']
for i in c:
for j in range(0,len(a)):
if (a[j+1] == a[len(a)]) is True:
break;
elif ((a[j] == a[j+1]) & (a[j+1] == i)) is True:
del[j]
e.join(a)
print(e)
Please show me how to solve this problem, or any other problem if in there.
How about maintaining a stack for consecutive vowels? whenever you see non-vowel string re-initialize the stack list and when you see vowels but are not consecutive you just add to the final list
stack=[]
new_list=[]
vowel=['a','i','o','u','e']
for i in your_string: # replace your string with actual string
if i not in vowel:
if len(stack) == 1:
new_list.append(stack[0])
new_list.append(i)
stack = []
else:
stack.append(i)
if len(stack) == 1:
new_list.append(stack[0])
You get a list out of index error because you are indexing at a value not in a
if (a[j+1] == a[len(a)]) is True:
a[len(a)] does not exist, arrays are zero indexed so they start from 0. An array with 5 items has index 0,1,2,3,4
the line should be:
if (a[j+1] == a[len(a) - 1]) is True:
Also 'is True' is redundant, so further refined:
if a[j+1] == a[len(a) - 1]:
Also is del[j] an error? should it be del a[j]?
If this is the case, the program will run into further errors as you are iterating over the entire Original size of the array but deleting values during this iteration, so it will look for items that no longer exist.
First detail is this: if (a[j+1] == a[len(a)]) is True: from what I understood this is to break the code when it is necessary. But that is completely unnecessary. Instead you should fix the number of iterations in the beginning, which should be for j in range(0,len(a)-1):
Another problem is that you aren't really iterating through the letters, just each comma separated phrases. If you put "Hello, World" you aren't checking the letters, you check "Hello" and " World". You might as well remove b and let a just be the raw input.
Since a would then be a string, to erase the i-th letter of a string you can use the function below.
def remove_jth(word, j):
word = word[:j] + word[j+1:]
Finally since you are using range, it will build a "list" that has the size len(a) when you start the for, but as you remove vowels, the length of a gets shorter and the range you had at the beginning will be to much. If you fix all of these things you should have it right
You can do it this way:
a=[]
b=str("a,a,a,b,e,e,e,c,x,d")
a=b.split(',')
c=['a','e','i','o','u']
j = 0
for i in c:
while j < len(a)-1:
if a[j] == a[j+1] and a[j] == i:
del a[j]
else:
j = j+1
j=0
Use a while loop to check through the list and delete consecutive duplicates. Then reset the the while loop back to zero and run through the list again.
Using a for loop will not work,if you are deleting items in the list that is being used to iterate over.
b=str("a,a,a,b,e,e,e,c,x,d") was just used to test the code.
To print the results you can just do print(a) it will print the list out.
I used this Stack Overflow post as reference.
I edited it to suit you:
result=original.replace('a','').replace('e',''),replace('i','').replace('o','').replace('u','')
original is your input string and result is your output string.
t=input()
st=""
vow=['a','e','i','o','u']
st+=t[0]
for i in range(1,len(t)):
if(t[i].lower() in vow):
if(t[i-1].lower() not in vow and i-1>=0):
st+=t[i]
else:
st+=t[i]
print(st)

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

Python: For loop is halving my list when called [duplicate]

This question already has answers here:
Loop "Forgets" to Remove Some Items [duplicate]
(10 answers)
Closed 5 years ago.
A file with approx. 127,000+ words is imported and put into a list
try:
dictionary = open("dictionary.txt", "r")
except:
print("Dictionary not found")
exit()
list_of_words = [word.rstrip('\n').rstrip('\r') for word in dictionary]
When the user enters a word length it checks to make sure the word is within the parameters.
def length_check(x):
while(1):
x = int(input("Please enter a word length: "))
if x >= 1 and x <=147:
return
else:
print ('enter proper length')
it then takes that word length and checks it against the words in the list and deletes any word in the list, thats not equal to "word_length"
def read_and_delete(x):
i = 0
for removal in x:
if len(x[i]) != word_length:
del x[i]
i += 1
elif len(x[i]) == word_length:
i += 1
else:
continue
print(len(list_of_words))
But for some reason, the outputted result is exactly half of the words in the list and I cannot see why as there is no divide at all in the code.
You are doing the mistake of iterating through the list and modifying it in the same time. You should always avoid that.
In your code del[i] creates a gap and then shifts all the subsequent numbers in the array, left by one position to fill the gap. When you increment i, you skip an element.
For completeness, this would fix your code.
def read_and_delete(x):
i = 0
for removal in x:
if len(x[i]) != word_length:
del x[i]
elif len(x[i]) == word_length:
i += 1
else:
continue
print(len(list_of_words))
Here is a better way of doing it
def read_and_delete(x):
return [word for word in x if len(word) == word_length]
This returns a new list and does not change the previous one.

Finding the index at which upon removing element string becomes palindrome

I'm writing the solution to this HackerRank problem - https://www.hackerrank.com/challenges/palindrome-index
I've tried this code:
T = int(raw_input())
for t in xrange(T):
s = raw_input()
index = -1
if s != s[::-1]:
for i in xrange(len(s)):
temp = s[:i:] + s[i+1::]
if temp == temp[::-1]:
index = i
break
print index
But when I submit it, out of the 14 test cases, around 8 take a long time to compute (~5-7 seconds) and 1 of them takes more than 10 seconds, so HackerRank doesn't even show the result (whether it gave the right output).
It seems my code is inefficient. Please help me out in making it run faster.
The easiest way to speed the code would be to remove slicing for every index in case that string isn't a palindrome. In case of maximum length string which is not a palindrome following line will generate over 200000 slices: temp = s[:i:] + s[i+1::].
You could start checking the string from start and beginning until you spot a difference. Once found you can generate slice which has either first or last letter removed and check if that's a palindrome. In case you removed the first character and result wasn't a palindrome you know that last character is the correct solution since the problem statement guarantees that:
T = int(raw_input())
for t in xrange(T):
s = raw_input()
length = len(s)
for i in xrange(length / 2):
if s[i] != s[length - i - 1]:
if s[i + 1:length - i] == s[length - i - 1:i:-1]:
print i
else:
print length - i - 1
break
else:
print -1
The most efficient way would be to check from both sides left and right and break on inequality:
for i in range(int(input())):
s=input()
if s==s[::-1]:
print(-1)
else:
for i in range(int(len(s)/2)):
if s[i]!=s[len(s)-1-i]:
print(i if ((s[:i]+s[i+1:])==(s[:i]+s[i+1:])[::-1]) else len(s)-1-i)
break
Apparently I'm a member of that site as well, executed my code and it passes all test cases with 0.01 s and 0.02s

Categories

Resources