Longest sub string and its length without repeated chars - python-3.x

def findLongestSubstring(string):
st = 0 # starting point of current substring.
maxlen = 0 # maximum length substring without repeating characters.
start = 0 # starting index of maximum length substring.
pos = {} # Hash Map to store last occurrence of each already visited character
pos[string[0]] = 0 #Last occurrence of first character is index 0
for i in range(1, len(string)):
# If this character is not present in hash, character, store this in hash.
if string[i] not in pos:
pos[string[i]] = i
else:
# If this character is present in hash then check if that occurrence
# is before or after starting point of current substring.
if pos[string[i]] >= st:
# find length of current substring and update maxlen and start accordingly.
currlen = i - st
if maxlen < currlen:
maxlen = currlen
start = st
# Next substring will start after the last occurrence of current
# character to avoid its repetition.
st = pos[string[i]] + 1
pos[string[i]] = i # Update last occurrence of current character.
# Compare length of last substring with maxlen & update maxlen and start accordingly.
if maxlen < i - st:
maxlen = i - st
start = st
# The required longest substring without repeating characters is from string[start]
#to string[start+maxlen-1].
print("Lenth is:", len(string[start : start + maxlen]) )
print( string[start : start + maxlen] )
return string[start : start + maxlen]
Above code works for the most part. But for below test case, it fail. What am I doing wrong? Code was copied from GeeksforGeeks. Code is returning "ba", instead of "bad".
assert(findLongestSubstring("babad") == "bad" )

Your last length check should work if you increment i by 1.
# Compare length of last substring with maxlen & update maxlen and start accordingly.
if maxlen < (i + 1) - st:
maxlen = (i + 1) - st
start = st

Related

logic for returning a substring with highest number of vowel

You are given with a string and length of a substring .You are required to determine the substring with highest number of vowels .The substring can be a combination of vowel and consonant but it should have the highest number of vowels.
example:
input
string= azerdii
length of substring=5
substrings= azerd,zerdi,erdii
erdii has highest number of vowels so output should be erdii
Kindly help me with the code in Python3
#fetch all substrings
string_is = 'azerdii'
sub = 5
length = len(string_is)
sub_ar = [string_is[i:j+1] for i in range(length) for j in range(i,length)]
#print(sub_ar)
#fetch substrings of a length = 5
sub_ar_is = []
for each in sub_ar:
if len(each) == 5:
sub_ar_is.append(each)
print(sub_ar_is)
data_dict = {}
data = ['a','e','i','o','u']
for each in sub_ar_is:
count = 0
for each_is in data:
count = count + each.count(each_is)
data_dict.update({each:count})
print(data_dict)
print("Substring is: ", max(data_dict, key=data_dict.get))
def findSubstring(s, k):
vowels = "aeiou"
return_output = ["Not found!"]
max_countt = 0
# loop size such that index don't gets out of range
length = len(s)-k+1
for i in range(length):
# temporary storage of vowel count
sum_count = 0
# getting string of desire size
output = s[i:i+k]
# count of vowels in the string
for vowel in vowels:
sum_count += output.count(vowel)
# if vowels in the string is greater than string having max vowels
# replace the max vowel string and number of max vowel count
if max_countt < sum_count:
return_output = output
max_countt = sum_count
# return output
return "".join(return_output)
print(findSubstring("azerdii", 5))

Why doesn't this function always return the longest palindromic substring in a string?

I wrote this solution to a codewars problem (https://www.codewars.com/kata/longest-palindrome). It passes all but one of the tests, in which it returns 2 instead of 7.
Why might this solution fail?
def longest_palindrome (s):
if s == '':
return 0
if len(s) == 1:
return 1
palindrome_lengths = []
for i in range(len(s)):
# determine all indices for the character
indices = []
for p, character in enumerate(s):
if character == s[i]:
indices.append(p)
# check if each substring is a palindrome and, if so, add length to palindrome_lengths
index = 1
while index < len(indices):
# grab the substring
substring = s[indices[0]:indices[index]+1]
# reverse the substring
reverse_substring = substring[::-1]
# if forward substring equals reverse, add length to a list of lengths
if substring == reverse_substring:
palindrome_lengths.append(len(substring))
index += 1
if palindrome_lengths == []:
return 1
else:
palindrome_lengths.sort(reverse=True)
return palindrome_lengths[0]
You never check any substring that doesn't start with the first occurrence of its first letter in the original string (for example, for the string "mamadam", you never test the substring starting with the second m).

replace an occurrence with a distinct number every loop

The first occurrence of the character in the string will be replaced with a 1, the second occurrence with a 2, etc.
ive tried using for loop and the max function to replace the last occurence but it doesnt seem to work.
string=str(input('string: '))
x=input('character: ')
list=[]
for i in range(len(string)):
if string[i]==x:
list.append(i)
Z=str(max(list))
print(string.replace(x,Z,[::-1]))
the output should be as following
string: departmentofcomputerscience
character: e
d1partm2ntofcomput3rsci4nc5
Here's a way to do it.
Use a counter for each character in the loop, and store values in the list, then merge the list. Use the current value if not equal to the character, counter otherwise:
string=str(input('string: '))
x=input('character: ')
# Use list to store results and a counter
l = []
counter = 0
for c in string:
if c==x:
counter += 1
l.append(str(counter))
else:
l.append(c)
# Merge the resulting list into string
res = "".join(l)
# Output the result
print(res)
For the input string: departmentofcomputerscience
and the character: e
The output is
d1partm2ntofcomput3rsci4nc5
Here is another way to achieve the goal using a list and the method replace():
string = str(input('string: '))
x = input('character: ')
list = []
for i in range(len(string)):
if string[i] == x:
list.append(i) # add all indexes to replace to the list
if len(list) > 0:
j = 0
for i in range(len(list)):
j += 1
string = string.replace(string[list[i]], str(j), 1) # replace the element once at time
print(string)
For string: departmentofcomputerscience
character: e
Output: d1partm2ntofcomput3rsci4nc5
def replace(s, c):
'''
#parameter s: input string
#parameter c: input character to be replaced
#return s: where every occurence of c is
replaced by it's nth occurence
'''
so = list(s)
j = 1
for i in range(len(so)):
if so[i] == c:
so[i] = str(j)
j = j + 1
return ''.join(so)

How can i remove the exact number of middle characters from a string?

I am trying to remove the number of middle characters in a string according to a given number. For example, if the string is mahir and I am told to remove one middle character, that would be h and the output would be mair, if the given number was 2, the output would have been mar.
I have worked out how the remove the middle characters but having troubles in removing it correctly. This is my code:
remover = int(input())
s = "mahir"
counter = len(s) - remover
while True:
h = len(s)//2
mod = (len(s) + 1) % 2
s = s[:h - mod] + s[h + 1:]
if len(s) == counter:
break
print(s)
If i enter remover more than one I end up getting an inifinte loop. How can i fix this and remove the correct number of middle characters?
You can slice the string like this:
s = 'mahir'
n = int(input())
i = (len(s) - n + 1) // 2
print(s[:i] + s[i + n:])

Is there a pythonic way to insert space characters at random positions of an existing string?

is there a pythonic way to implement this:
Insert /spaces_1/ U+0020 SPACE
characters into /key_1/ at random
positions other than the start or end
of the string.
?
There /spaces_1/ is integer and /key_1/ is arbitrary existing string.
Thanks.
strings in python are immutable, so you can't change them in place. However:
import random
def insert_space(s):
r = random.randint(1, len(s)-1)
return s[:r] + ' ' + s[r:]
def insert_spaces(s):
for i in xrange(random.randrange(len(s))):
s = insert_space(s)
return s
Here's a list based solution:
import random
def insert_spaces(s):
s = list(s)
for i in xrange(len(s)-1):
while random.randrange(2):
s[i] = s[i] + ' '
return ''.join(s)
I'm going to arbitrarily decide you never want two spaces inserted adjacently - each insertion point used only once - and that "insert" excludes "append" and "prepend".
First, construct a list of insertion points...
insert_points = range (1, len (mystring))
Pick out a random selection from that list, and sort it...
import random
selected = random.sample (insert_points, 5)
selected.sort ()
Make a list of slices of your string...
selected.append (len (mystring)) # include the last slice
temp = 0 # start with first slice
result = []
for i in selected :
result.append (mystring [temp:i])
temp = i
Now, built the new string...
" ".join (result)
Just because no one used map yet:
import random
''.join(map(lambda x:x+' '*random.randint(0,1), s)).strip()
This method inserts a given number of spaces to a random position in a string and takes care that there are no double spaces after each other:
import random
def add_spaces(s, num_spaces):
assert(num_spaces <= len(s) - 1)
space_idx = []
space_idx.append(random.randint(0, len(s) - 2))
num_spaces -= 1
while (num_spaces > 0):
idx = random.randint(0, len(s) - 2)
if (not idx in space_idx):
space_idx.append(idx)
num_spaces -= 1
result_with_spaces = ''
for i in range(len(s)):
result_with_spaces += s[i]
if i in space_idx:
result_with_spaces += ' '
return result_with_spaces
If you want to add more than one space, then go
s[:r] + ' '*n + s[r:]
Here it comes...
def thePythonWay(s,n):
n = max(0,min(n,25))
where = random.sample(xrange(1,len(s)),n)
return ''.join("%2s" if i in where else "%s" for i in xrange(len(s))) % tuple(s)
We will randomly choose the locations where spaces will be added - after char 0, 1, ... n-2 of the string (n-1 is the last character, and we will not place a space after that); and then insert the spaces by replacing the characters in the specified locations with (the original character) + ' '. This is along the lines of Steve314's solution (i.e. keeping the assumption that you don't want consecutive spaces - which limits the total spaces you can have), but without using lists.
Thus:
import random
def insert_random_spaces(original, amount):
assert amount > 0 and amount < len(original)
insert_positions = sorted(random.sample(xrange(len(original) - 1), amount))
return ''.join(
x + (' ' if i in insert_positions else '')
for (i, x) in enumerate(original)
)

Resources