String index out of range, Python - python-3.x

code for a function which increments a string, to create a new string. If the string already ends with a number, the number should be incremented by 1. If the string does not end with a number the number 1 should be appended to the new string.
The output is correct but it is showing a String index out of range error. Can someone help me on where and how the string index is out of range?
test cases,expected output:
(increment_string("foo"), "foo1"),(increment_string("foobar001"), "foobar002"),(increment_string("foobar1"), "foobar2"),(increment_string("foobar00"), "foobar01"),("foobar99"), "foobar100"),("foobar099"), "foobar100"),(increment_string(""), "1")
def increment_string(strng):
if strng[-1].isdigit():
exp_strng=strng[::-1]
new_strng=""
new_strng1=""
for i in exp_strng:
if i.isdigit():
new_strng+=i
else:
break
new_strng=new_strng[::-1]
new_strng1=int(new_strng)+1
new_strng1='{num:{fill}{width}}'.format(num=new_strng1, fill='0', width=len(new_strng))
return(strng[:-len(new_strng)]+new_strng1)
else:
strng+="1"
return(strng)

Since you gave us more information on the test cases given, you can bypass the edge case of an empty string by modifying the if statement:
def increment_string(strng):
# Add it here #
if strng == "":
return "1"
elif strng[-1].isdigit():
exp_strng = strng[::-1]
new_strng = ""
new_strng1 = ""
for i in exp_strng:
if i.isdigit():
new_strng += i
else:
break
new_strng = new_strng[::-1]
new_strng1 = int(new_strng) + 1
new_strng1 = '{num:{fill}{width}}'.format(num=new_strng1, fill='0', width=len(new_strng))
return strng[:-len(new_strng)] + new_strng1
else:
strng += "1"
return strng

If think this would be a better solution to your problem:
from re import search
def increment_string(s):
number = search('\d+$', s)
if number != None:
number = number.group()
first_part = s.split(number)[0]
return first_part + str(int(number)+1)
else:
return s + '1'
I don't know what you want when the number is 9 though: 0 or 10. This code produces 10.

the error was caused when empty string is passed. and I resolved it by adding one more if else:(thanks to Skam)
def increment_string(strng):
if len(strng)>0:
if strng[-1].isdigit():
exp_strng=strng[::-1]
new_strng=""
new_strng=""
for i in exp_strng:
if i.isdigit():
new_strng+=i
else:
break
new_strng=new_strng[::-1]
new_strng1=int(new_strng)+1
new_strng1=str(new_strng1)
new_strng1=new_strng1.zfill(len(new_strng))
return(strng[:-len(new_strng)]+new_strng1)
else:
strng+="1"
return(strng)
else:
strng+="1"
return(strng)

Related

Write a program to check the overlapping of one string's suffix with the prefix of another string

a = input()
b = input()
def longestSubstringFinder(string1, string2):
answer = ""
len1, len2 = len(string1), len(string2)
for i in range(len1):
match = ""
for j in range(len2):
if (i + j < len1 and string1[i + j] == string2[j]):
match += string2[j]
else:
if (len(match) > len(answer)): answer = match
match = ""
if answer == '':
return 'No overlapping'
else:
return answer
print(longestSubstringFinder(a, b))
in the above code, not getting the expected outcome for the input
correct
wrong
My output: e
expected output: No overlapping
Some issues:
the else block should not allow the inner loop to continue: when you have a mismatch, you should not try matches with higher values of j, but you should exit that loop and try with the next value for i. So there needs to be a break in the else block
the condition len(match) > len(answer) is not enough to identify a solution. The reason for getting into the else block might have been that the characters didn't match, so in that case you should never update answer.
On the other hand, the update of answer is not happening now when the inner loop ends normally, i.e. when all compared characters were equal and i + j < len1 was always true. This case happens when the second input string is a suffix of the first. So you must make the update to answer somewhere else, so you also catch this case.
Here is the correction to your code, dealing with these issues:
def longestSubstringFinder(string1, string2):
answer = ""
len1, len2 = len(string1), len(string2)
for i in range(len1):
match = ""
for j in range(len2):
if (i + j < len1 and string1[i + j] == string2[j]):
match += string2[j]
# Move the assignment to answer here, and add condition that
# this was the last character of string1:
if i + j == len1 - 1 and len(match) > len(answer): answer = match
else:
break # Necessary!
if answer == '':
return 'No overlapping'
else:
return answer
With the use of string slicing, and comparing those slices instead of individual characters, you can make your code shorter and run faster.
Using RegEX, you can do it with lesser lines of code. I'm assuming you're a beginner in Python. If you are, then please learn RegEx and List Comprehension for this type of code.
import re
str1, str2 = input(), input()
def longestSubstringFinder(string1, string2):
list_of_subsets = [str1.replace(str1[:i], '') for i in range(len(str1))]
intersect = [re.search('^'+slc, str2).group() for slc in list_of_subsets if re.search('^'+slc, str2)]
if len(intersect) == 0:
return 'No overlapping'
else:
return intersect[0]
print(longestSubstringFinder(str1, str2))
a = str(input())
b = str(input())
g=len(a)-1
prefix = "No overlapping"
for i in range(len(a)):
if a[(g-i):] == b[:i+1]:
prefix = b[:i+1]
print(prefix)

I need a help in writing a function that counts the digits and letters separately then returns the result in a dictionary format

I have been working on the python challenge question and I have been stuck it on for a while. Below is the question.
Write a function that takes a string and calculates the number of letters and digits within it. Return the result in a dictionary.
Examples:
count_all("Hello World") ➞ { "LETTERS": 10, "DIGITS": 0 }
count_all("H3ll0 Wor1d") ➞ { "LETTERS": 7, "DIGITS": 3 }
count_all("149990") ➞ { "LETTERS": 0, "DIGITS": 6 }
Notes:
Tests contain only alphanumeric characters.
Spaces are not letters.
All tests contain valid strings.
The function should return dictionary
I have written a code to solve it but I have been getting a 'Too many positional arguments for function call.
def count_all(string):
d = 0
l = 0
for c in string:
if c.isdigit():
d=d+1
elif c.isalpha():
l=l+1
else:
pass
print(count_all("string", "l"))
print(count_all("string", "d"))
what have I done wrong exactly?
Pretty much all you need to do is make it so that you're passing just 1 string to your function, like so: print(count_all("letters and numbers 12345")). And second, you need to change the output so that it should return a dict, like so: return {"letters": l, "digits": d}.
Try this out
def countStuff(argString = None):
resultDict = {"Letters" : 0, "Numbers" : 0}
if argString is None:
print("-_-")
for i in argString:
if i.isdigit():
resultDict["Numbers"] += 1
elif i.lower().islower():
resultDict["Letters"] += 1
else:
pass
print(resultDict)
alphacount = 0
numcount = 0
str1 = input("Enter a sentence: ")
for x in str1:
if x.isalpha(): # Check the Albhabets in String
alphacount+=1
elif x.isdigit(): # Check the digits in String
numcount+=1
else:
continue
print('LETTERS '+ str(alphacount))
print('DIGITS '+ str(numcount))

My job is to write a function which increments a string, to create a new string

Why my code is wrong which outputs an error
def increment_string(strng):
if strng == '':
return '1'
elif strng.isdigit():
number= int(''.join(filter(str.isdigit,strng)))
return re.sub('\d+',str(number +1),strng)
return strng + str(1)
Output:
increment_string("foobar001")
It should return 'foobar002' but it is returning 'foobar0011'
It gives 'foobar0011' because the program control is not entered into the elif block and it returned strng + str(1).
Program control not entered the elif block because the function strng.isdigit() returns false. This returns true only if each character in strng is a digit. My suggestion is to replace isdigit() function with the isalnum() function. Because isalnum() function verifies that each character in a string is either an alphabet or a digit.
Here is my solution :
import re
def increment_string(strng):
if strng == '':
return '1'
elif strng.isalnum():
number = int(''.join(filter(str.isdigit, strng)))
return re.sub('\d+', str(number + 1), strng)
return strng + str(1)
print(increment_string("foobar001"))
The problem with your code is explained below:
def increment_string(strng):
#...
'''
this is checking if the passed string is a digit. Since you are
passing "foobar001", which is not a digit, elif condition is not executed,
and goes directly to the last return statement where you simple add "1" to the string
'''
elif strng.isdigit():
#...
return strng + str(1)
To meet the requirements given in the question, try this out:
def increment_string(strng):
match = re.search('(\d+)', strng)
if match:
num = match.group(1)
newNum = str(int(num) + 1)
return re.sub('\d+', str(newNum.zfill(len(num))), strng)
else:
return strng
Note : This returns the same input string in case no number is present.
To know more about zfill, check here.

Standard output is empty in python3

This is a program of finding a string is palindrome or not. But When I run this code I got error "standard output is error".
class Palindrome:
#staticmethod
def is_palindrome(word):
flag = word;
lengths = len(word);
j=lengths;
lengths = lengths/2;
lengths = int(lengths);
for i in lengths:
if (word[i] == word[j]):
count = count+1;
j = j-1;
if (count == lengths):
r = "yes";
else:
r = "no";
return r
word = input();
print(Palindrome.is_palindrome(word));
There are some mistakes in the code,
First of all, you are trying to iterate a int like for i in lengths which will throw you an error. You must be using it like for i in range(lengths).
Also, you are trying to do count = count+1 even before count is initialized, which will be throwing an error. To solve this you can initialize the variable count before the loop to 0.
Another issue with the code is that, you are tying to compare word[i] and word[j] where j is length which is not possible because for a string of length n, index runs from 0 to n-1. Therefore you must be using length-1 as j.
Also, there is no need for semicolon in Python.
Correcting all the things that I have mentioned above you can re-write the code like this
class Palindrome:
#staticmethod
def is_palindrome(word):
flag = word
lengths = len(word)
j=lengths-1
lengths = lengths/2
lengths = int(lengths)
count = 0
for i in range(lengths):
if (word[i] == word[j]):
count = count+1
j = j-1
if (count == lengths):
r = "yes"
else:
r = "no"
return r
word = input()
print(Palindrome.is_palindrome(word))
If you can use ~ operator you can tidy up the code to a great extend. It can be done like this.
class Palindrome:
#staticmethod
def is_palindrome(word):
if all(word[i] == word[~i] for i in range(len(word) // 2)):
return "yes"
else:
return "no"
word = input()
print(Palindrome.is_palindrome(word)
If you want to know how the ~ operator works take a look at this post.
You can improve it further if you can use indexing to reverse the string. If you can reverse the string and then check with the original one.
class Palindrome:
#staticmethod
def is_palindrome(word):
if word == word[::-1]:
return "yes"
else:
return "no"
word = input()
print(Palindrome.is_palindrome(word)

Count on which loop text was entered and display as index

I'm working on a small program which takes a text input - and then places each of these items in a dictionary alongside which line they were entered on. At the moment if I enter 4 lines of text. It'll take them all out correctly, but every word will be set to the value 4 - instead of the loop it was inputted on. I've removed all the other functions from my code (remove punct, remove stopwords, stemwords, etc). to make this clearer.
from string import *
function = False
words_split = []
lineNumber=0
final_value = []
def indexer(t):
global words_split
words = t.split();
for word in words:
words_split.append(word)
def dict_print():
for keys in Dict:
output = keys + " " + str(Dict[keys][0])
i= 1
while i < len(Dict[keys]):
output = output + ", " + str(Dict[keys][i])
i = i + 1
print(output)
print("Please type a line and hit 'Enter' or type a single fullstop followed by 'Enter' to exit \n")
text = ""
while function == False :
if(text == "."):
print("The index is:")
function = True
dict_print()
else:
Dict = {}
text = input()
lineNumber += 1
for word in words_split:
if word in Dict:
if lineNumber not in Dict[word]:
Dict[word] = Dict[word] + [lineNumber]
else:
Dict[word] = [lineNumber]
indexer(text)
My global variable was causing the issue. I'll leave this up with my completed full code in case someone else runs into the same issue (:
https://repl.it/#Glaschu/AdmiredSteelCardinal

Resources