Run length encoding python; String index out of range error - python-3.x

I'm trying to implement run length encoding into python with this code.
When I run it I get string index out of range error, not sure what is causing the error though
text="aaabbbcc"
def encode(text):
prev = text[0]
lentext = len(text)
i = 1
while prev == text[i] and i < lentext:
i += 1
return prev + str(i) + encode(text[i:])
print(encode(text))

Before you can check if i is less than the text length, you already try to access the ith element of text, which causes the exception. Instead, write your while loop as:
while i < lentext and prev == text[i]:
This will make sure i is in range before trying to access that index of text.
Also note that if you are going to use a recursive algorithm, you need a base case to exit the chain of recursive calls from. Probably something like the following at the top of your function:
if not text:
return ""
So all together:
text="aaabbbcc"
def encode(text):
if not text:
return ""
prev = text[0]
lentext = len(text)
i = 1
while i < lentext and prev == text[i]:
i += 1
return prev + str(i)+ encode(text[i:])
print(encode(text))

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)

Use Python to reverse the words in a sentence

The question was: Return a sentence with the words reversed
>>> master_yoda('I am home')
'home am I'
It will eventually reverse the words of the line.
I am learning and performing Python in Jupyter Notebook.
def master_yoda(string):
l = string.split()``
p = len(string) - 1
final = ''
while p<0:
final = final + ' ' + s[p]
p = p-1
print (final)
master_yoda('Hello my name is Aryan')
The output is nothing..
No syntax errors , but still no output ...
Perhaps you should try this.
def master_yoda(string):
reversed_list = string.split(' ')
reversed_list.reverse()
reversed_string = ' '.join(reversed_list)
print(reversed_string)
master_yoda("i am home")
The big problem with the code is that you were testing for p < 0 but since p starts off with a positive value, the code never enters the while loop. You should really have been testing for p >= 0. The following code should do what you want, they way you seem to want it to:
def master_yoda(string):
l = string.split()
p = len(l) - 1
final = l[p]
p -= 1
while p >= 0:
final += ' ' + l[p]
p -= 1
return final
Note that this implementation fails if an empty string is passed as input. I tried to keep the code in the spirit of your own code and checking for an empty string would make it more complex. The simplest and most robust solution would be:
def master_yoda(string):
return ' '.join(reversed(string.split()))

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)

Use Python function to change string "oalalaeah" to "hello"

Hi I am learning python I was just trying to resolve the above example.That is make a function to change the string "oalalaeah" to "hello". Notice that 'hello' is the alternate letter starting from the back. I can do both individually. Important: I want to do it using only python functions()
`def rev_str(str1):
new_str = ''
index = len(str1)
while index > 0:
new_str += str1[index-1]
index = index - 1
return new_str`
print(rev_str('oalalaeah'))
to reverse the string to "haealalao"
later use:
def rev_alt(str2):
fin_str = ''
index = -2
while index < len(str2)-1:
fin_str += str2[index+2]
index = index + 2
return fin_str
print(rev_alt('haealalao'))
This gives me "hello" but these are 2 separate operations. I want to have 1 function that that will turn "oalalaeah" to "hello". I am sorry if this is too easy. Its driving me crazy
def rev_str(str1):
new_str = ''
index = len(str1)
while index > 0:
new_str += str1[index-1]
index = index - 1
return new_str
This is taking each letter in the string from the end to the beginning by decreasing the index by one on each iteration. Literally the only change needed to take every second letter is to decrease the index by two on each iteration:
def rev_str(str1):
new_str = ''
index = len(str1)
while index > 0:
new_str += str1[index-1]
index = index - 2 # 👈 here
return new_str
print(rev_str('oalalaeah')) # hello
The pythonic version of this is the built-in slice syntax:
print('oalalaeah'[::-2]) # hello

choose the middle in merge sort

I was trying to complete a merge sort in Python. I found when I use middle = (len(x)-1)//2, the right part was in infinity loop and never reached the base case, but if I changed middle = len(x)//2, it worked normally. So why?
The solution does lie in the middle variable. After abit of experimenting I found that using middle = len(alist)//2 fixes the whole program. Despite this not being technically mathematical, it does seem to work.
You could also increase efficiency by replacing the if and else at the start of the mergesort() function with a simple if len(alist) > 1: and then return alist at the end of the function, rather than at the end of each if and else, if that makes sense. (This would also mean you can just replace the com variable with alist).
For reference, heres my code (some variables are renamed):
from random import shuffle
### INIT ###
arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
shuffle(arr)
print("Starting List: " + str(arr))
### SORT ###
# Merge
def merge(left,right):
sorted = []
i, j = 0, 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
sorted.append(left[i])
i += 1
else:
sorted.append(right[j])
j += 1
sorted += right[j:]
sorted += left[i:]
return sorted
# Decomposition
def sort(arr):
#print(arr)
if len(arr) > 1:
middle = len(arr)//2
left = sort(arr[:middle])
right = sort(arr[middle:])
arr = merge(left, right)
return arr
arr = sort(arr)
print("Ending List: " + str(arr))

Resources