How can i get count of irregular repeating characters? - python

Input is xyz = 'aaabbbaaa', I want output as 3a3b3a
xyz = 'aaabbbaaa'
p = xyz[0]
i = 0
out = {}
while i < len(xyz):
if p == xyz[i]:
if xyz[i] not in out:
out[xyz[i]] = []
out[xyz[i]].append(xyz[i])
else:
p = xyz[i]
i += 1
print(out)
Help me, How can i achieve this??

This is likely the simplest method and easiest to understand.
Create a tally variable and increment it when you see repeating characters, then when you see a non repeating character write the previous character and the tally to a string and start the tally back to 1.... repeat until string ends
xyz = 'aaabbbaaa'
tally = 1
string = ''
prev = xyz[0]
for char in xyz[1:]:
if char == prev:
tally += 1
else:
string += str(tally) + prev
prev = char
tally = 1
string += str(tally) + prev
print(string) # 3a3b3a

what result do you expect to get if the string has single characters? suppose we should just skip a single character:
from re import sub
s = 'aabbbcaaabc'
sub(r'(\w)\1*',lambda m: f"{l if (l:=len(m[0]))>1 else ''}{m[1]}",s)
>>>
# '2a3bc3abc'

Related

Python Inserting a string

I need to insert a string (character by character) into another string at every 3rd position
For example:- string_1:-wwwaabkccgkll
String_2:- toadhp
Now I need to insert string2 char by char into string1 at every third position
So the output must be wwtaaobkaccdgkhllp
Need in Python.. even Java is ok
So i tried this
Test_str="hiimdumbiknow"
challenge="toadh"
new_st=challenge [k]
Last=list(test_str)
K=0
For i in range(Len(test_str)):
if(i%3==0):
last.insert(i,new_st)
K+=1
and the output i get
thitimtdutmbtiknow
You can split test_str into sub-strings to length 2, and then iterate merging them with challenge:
def concat3(test_str, challenge):
chunks = [test_str[i:i+2] for i in range(0,len(test_str),2)]
result = []
i = j = 0
while i<len(chunks) or j<len(challenge):
if i<len(chunks):
result.append(chunks[i])
i += 1
if j<len(challenge):
result.append(challenge[j])
j += 1
return ''.join(result)
test_str = "hiimdumbiknow"
challenge = "toadh"
print(concat3(test_str, challenge))
# hitimoduambdikhnow
This method works even if the lengths of test_str and challenge are mismatching. (The remaining characters in the longest string will be appended at the end.)
You can split Test_str in to groups of two letters and then re-join with each letter from challenge in between as follows;
import itertools
print(''.join(f'{two}{letter}' for two, letter in itertools.zip_longest([Test_str[i:i+2] for i in range(0,len(Test_str),2)], challenge, fillvalue='')))
Output:
hitimoduambdikhnow
*edited to split in to groups of two rather than three as originally posted
you can try this, make an iter above the second string and iterate over the first one and select which character should be part of the final string according the position
def add3(s1, s2):
def n():
try:
k = iter(s2)
for i,j in enumerate(s1):
yield (j if (i==0 or (i+1)%3) else next(k))
except:
try:
yield s1[i+1:]
except:
pass
return ''.join(n())
def insertstring(test_str,challenge):
result = ''
x = [x for x in test_str]
y = [y for y in challenge]
j = 0
for i in range(len(x)):
if i % 2 != 0 or i == 0:
result += x[i]
else:
if j < 5:
result += y[j]
result += x[i]
j += 1
get_last_element = x[-1]
return result + get_last_element
print(insertstring(test_str,challenge))
#output: hitimoduambdikhnow

Trying to find the longest substring without repeating characters

For example, if the string was "pwwkew", the longest substring without repeating characters would be "wke".
def longest_non_repeating_substring():
count = 0
current_longest = 0
consideration = []
possible_longest = []
while count > len(string):
current_char = string[count:count+1]
consideration.append(current_char)
for i in range(len(consideration)):
if current_char == consideration[i]:
possible_longest.append(current_longest)
current_longest = 0
del consideration[:]
consideration.append(current_char)
current_longest += 1
count += 1
return max(possible_longest)
longest_non_repeating_substring("pwwkew")
So, I iterate through the string one character at a time. At each character, I add it to my array consideration, and check if that current character already exists there. If it does, I reset the array consideration, make current longest zero, and leave in the current character in the array. If the current character isnt there then I increase the counter and the length of the current longest. It seems very logical to me, but this is wrong. Anyone know what gives?
I think the given code looks a little bit complicated. You could try to use something similar to this:
def longest_non_repeating_substring(string):
count = 0
current_longest = []
current_candidate = []
# Iterate over all characters in the string
while count < len(string):
current_char = string[count:count+1]
# Check if we have a duplicate
if current_char in current_candidate:
# if so create a new candidate with the substring after the duplicate
index_duplicate = current_candidate.index(current_char)
current_candidate = current_candidate[index_duplicate+1:]
# Append current character to candidate
current_candidate.append(current_char)
# Check if candidate is longer than what we had before; if so make candidate current longest
if len(current_candidate) > len(current_longest):
current_longest = current_candidate
count = count +1
# Convert list of current_longest to string
current_longest_str = ''.join(current_longest)
return current_longest_str
string = 'pwwkew'
longest = longest_non_repeating_substring(string)
print(longest) # Output: wke
I see that others already pointed you in the right direction. I propose the following solution:
def longest_non_repeating_chars_substring(string: str):
longest_substring = None
current_substring = ''
for i, char in enumerate(string):
if i > 0:
if char != string[i - 1] or current_substring == '':
current_substring += char
else:
longest_substring = current_substring
current_substring = char
else:
current_substring += char
if len(current_substring) > len(longest_substring):
return current_substring
return longest_substring
Let me know of your thoughts!

Python: how to replace a substring with a number of its occurences?

Let's say I have a string presented in the following fashion:
st = 'abbbccccaaaAAbccc'
The task is to encode it so that single characters are followed by a number of their occurences:
st = 'a1b3c4a3A2b1c3'
I know one possible solution but it's too bulky and primitive.
s = str(input())
l = len(s)-1
c = 1
t = ''
if len(s)==1:
t = t +s+str(c)
else:
for i in range(0,l):
if s[i]==s[i+1]:
c +=1
elif s[i]!=s[i+1]:
t = t + s[i]+str(c)
c = 1
for j in range(l,l+1):
if s[-1]==s[-2]:
t = t +s[j]+str(c)
elif s[-1]!=s[-2]:
t = t +s[j]+str(c)
c = 1
print(t)
Is there any way to solve this shortly and elegantly?
P.S: I'm an unexperienced Python user and a new StackOverflow member, so I beg my pardon if the question is asked incorrectly.
Take advantage of the standard library:
from itertools import groupby
st = "abbbccccaaaAAbccc"
print("".join("{}{}".format(key, len(list(group))) for key, group in groupby(st)))
Output:
a1b3c4a3A2b1c3
>>>
just loop through and count. There are more graceful snippets but this will get the job done and is clear:
count = 1
char = st[0]
new_st = []
for c in st[1:]:
if c == char:
count += 1
else:
new_st.append(char + str(count))
char = c
count = 1
new_st.append(char + str(count))
s2= "".join(new_st)
print(s2) # 'a1b3c4a3A2b1c3'
If you want a fancy recursive solution:
def compose(s):
if not s:
return ""
count = 1
for char in s[1:]:
if s[0] != char:
break
count += 1
return s[0] + str(count) + compose(s[count:])

Intersection between two list of strings python

This is in reference to problem that is done in Java:
Finding the intersection between two list of string candidates.
I tried to find an equivalent solution in python:
def solution(S):
length = len(S)
if length == 0:
return 1
count = 0
i = 0
while i <= length:
prefix = S[0:i:]
suffix = S[length-i:length]
print suffix
if prefix == suffix:
count += 1
i += 1
return count
print solution("")
print solution("abbabba")
print solution("codility")
I know I am not doing the step in terms of suffix.
I am getting the values as 1,4,2 instead of 1,4,0
Your current code runs through giving the following prefix, suffix pairs for the second two examples:
a a
ab ba
abb bba
abba abba
abbab babba
abbabb bbabba
abbabba abbabba
c y
co ty
cod ity
codi lity
codil ility
codili dility
codilit odility
codility codility
I presume you are trying to return the number of times the first n characters of a string are the same as the last n. The reason the word codility is returning 2 is because you are starting the index from zero, so it is matching the empty string and the full string. Try instead:
def solution(S):
length = len(S)
if length == 0:
return 1
count = 0
i = 1 # Don't test the empty string!
while i < length: # Don't test the whole string! Use '<'
prefix = S[:i] # Up to i
suffix = S[length-i:] # length - i to the end
print prefix, suffix
if prefix == suffix:
count += 1
i += 1
return count
print solution("")
print solution("abbabba")
print solution("codility")
This returns 1, 2, 0.
Perhaps you were looking to test if the prefix is the same as the suffix backwards, and only test half the length of the string? In this case you should try the following:
def solution(S):
length = len(S)
if length == 0:
return 1
count = 0
i = 1 # Don't test the empty string!
while i <= (length + 1)/2: # Test up to halfway
prefix = S[:i] # Up to i
suffix = S[:length-i-1:-1] # Reverse string, up to length - i - 1
print prefix, suffix
if prefix == suffix:
count += 1
i += 1
return count
print solution("")
print solution("abbabba")
print solution("codility")
This returns 1, 4, 0.

Finding longest substring in alphabetical order

EDIT: I am aware that a question with similar task was already asked in SO but I'm interested to find out the problem in this specific piece of code. I am also aware that this problem can be solved without using recursion.
The task is to write a program which will find (and print) the longest sub-string in which the letters occur in alphabetical order. If more than 1 equally long sequences were found, then the first one should be printed. For example, the output for a string abczabcd will be abcz.
I have solved this problem with recursion which seemed to pass my manual tests. However when I run an automated tests set which generate random strings, I have noticed that in some cases, the output is incorrect. For example:
if s = 'hixwluvyhzzzdgd', the output is hix instead of luvy
if s = 'eseoojlsuai', the output is eoo instead of jlsu
if s = 'drurotsxjehlwfwgygygxz', the output is dru instead of ehlw
After some time struggling, I couldn't figure out what is so special about these strings that causes the bug.
This is my code:
pos = 0
maxLen = 0
startPos = 0
endPos = 0
def last_pos(pos):
if pos < (len(s) - 1):
if s[pos + 1] >= s[pos]:
pos += 1
if pos == len(s)-1:
return len(s)
else:
return last_pos(pos)
return pos
for i in range(len(s)):
if last_pos(i+1) != None:
diff = last_pos(i) - i
if diff - 1 > maxLen:
maxLen = diff
startPos = i
endPos = startPos + diff
print s[startPos:endPos+1]
There are many things to improve in your code but making minimum changes so as to make it work. The problem is you should have if last_pos(i) != None: in your for loop (i instead of i+1) and you should compare diff (not diff - 1) against maxLen. Please read other answers to learn how to do it better.
for i in range(len(s)):
if last_pos(i) != None:
diff = last_pos(i) - i + 1
if diff > maxLen:
maxLen = diff
startPos = i
endPos = startPos + diff - 1
Here. This does what you want. One pass, no need for recursion.
def find_longest_substring_in_alphabetical_order(s):
groups = []
cur_longest = ''
prev_char = ''
for c in s.lower():
if prev_char and c < prev_char:
groups.append(cur_longest)
cur_longest = c
else:
cur_longest += c
prev_char = c
return max(groups, key=len) if groups else s
Using it:
>>> find_longest_substring_in_alphabetical_order('hixwluvyhzzzdgd')
'luvy'
>>> find_longest_substring_in_alphabetical_order('eseoojlsuai')
'jlsu'
>>> find_longest_substring_in_alphabetical_order('drurotsxjehlwfwgygygxz')
'ehlw'
Note: It will probably break on strange characters, has only been tested with the inputs you suggested. Since this is a "homework" question, I will leave you with the solution as is, though there is still some optimization to be done, I wanted to leave it a little bit understandable.
You can use nested for loops, slicing and sorted. If the string is not all lower-case then you can convert the sub-strings to lower-case before comparing using str.lower:
def solve(strs):
maxx = ''
for i in xrange(len(strs)):
for j in xrange(i+1, len(strs)):
s = strs[i:j+1]
if ''.join(sorted(s)) == s:
maxx = max(maxx, s, key=len)
else:
break
return maxx
Output:
>>> solve('hixwluvyhzzzdgd')
'luvy'
>>> solve('eseoojlsuai')
'jlsu'
>>> solve('drurotsxjehlwfwgygygxz')
'ehlw'
Python has a powerful builtin package itertools and a wonderful function within groupby
An intuitive use of the Key function can give immense mileage.
In this particular case, you just have to keep a track of order change and group the sequence accordingly. The only exception is the boundary case which you have to handle separately
Code
def find_long_cons_sub(s):
class Key(object):
'''
The Key function returns
1: For Increasing Sequence
0: For Decreasing Sequence
'''
def __init__(self):
self.last_char = None
def __call__(self, char):
resp = True
if self.last_char:
resp = self.last_char < char
self.last_char = char
return resp
def find_substring(groups):
'''
The Boundary Case is when an increasing sequence
starts just after the Decresing Sequence. This causes
the first character to be in the previous group.
If you do not want to handle the Boundary Case
seperately, you have to mak the Key function a bit
complicated to flag the start of increasing sequence'''
yield next(groups)
try:
while True:
yield next(groups)[-1:] + next(groups)
except StopIteration:
pass
groups = (list(g) for k, g in groupby(s, key = Key()) if k)
#Just determine the maximum sequence based on length
return ''.join(max(find_substring(groups), key = len))
Result
>>> find_long_cons_sub('drurotsxjehlwfwgygygxz')
'ehlw'
>>> find_long_cons_sub('eseoojlsuai')
'jlsu'
>>> find_long_cons_sub('hixwluvyhzzzdgd')
'luvy'
Simple and easy.
Code :
s = 'hixwluvyhzzzdgd'
r,p,t = '','',''
for c in s:
if p <= c:
t += c
p = c
else:
if len(t) > len(r):
r = t
t,p = c,c
if len(t) > len(r):
r = t
print 'Longest substring in alphabetical order is: ' + r
Output :
Longest substring in alphabetical order which appeared first: luvy
Here is a single pass solution with a fast loop. It reads each character only once. Inside the loop operations are limited to
1 string comparison (1 char x 1 char)
1 integer increment
2 integer subtractions
1 integer comparison
1 to 3 integer assignments
1 string assignment
No containers are used. No function calls are made. The empty string is handled without special-case code. All character codes, including chr(0), are properly handled. If there is a tie for the longest alphabetical substring, the function returns the first winning substring it encountered. Case is ignored for purposes of alphabetization, but case is preserved in the output substring.
def longest_alphabetical_substring(string):
start, end = 0, 0 # range of current alphabetical string
START, END = 0, 0 # range of longest alphabetical string yet found
prev = chr(0) # previous character
for char in string.lower(): # scan string ignoring case
if char < prev: # is character out of alphabetical order?
start = end # if so, start a new substring
end += 1 # either way, increment substring length
if end - start > END - START: # found new longest?
START, END = start, end # if so, update longest
prev = char # remember previous character
return string[START : END] # return longest alphabetical substring
Result
>>> longest_alphabetical_substring('drurotsxjehlwfwgygygxz')
'ehlw'
>>> longest_alphabetical_substring('eseoojlsuai')
'jlsu'
>>> longest_alphabetical_substring('hixwluvyhzzzdgd')
'luvy'
>>>
a lot more looping, but it gets the job done
s = raw_input("Enter string")
fin=""
s_pos =0
while s_pos < len(s):
n=1
lng=" "
for c in s[s_pos:]:
if c >= lng[n-1]:
lng+=c
n+=1
else :
break
if len(lng) > len(fin):
fin= lng`enter code here`
s_pos+=1
print "Longest string: " + fin
def find_longest_order():
`enter code here`arr = []
`enter code here`now_long = ''
prev_char = ''
for char in s.lower():
if prev_char and char < prev_char:
arr.append(now_long)
now_long = char
else:
now_long += char
prev_char = char
if len(now_long) == len(s):
return now_long
else:
return max(arr, key=len)
def main():
print 'Longest substring in alphabetical order is: ' + find_longest_order()
main()
Simple and easy to understand:
s = "abcbcd" #The original string
l = len(s) #The length of the original string
maxlenstr = s[0] #maximum length sub-string, taking the first letter of original string as value.
curlenstr = s[0] #current length sub-string, taking the first letter of original string as value.
for i in range(1,l): #in range, the l is not counted.
if s[i] >= s[i-1]: #If current letter is greater or equal to previous letter,
curlenstr += s[i] #add the current letter to current length sub-string
else:
curlenstr = s[i] #otherwise, take the current letter as current length sub-string
if len(curlenstr) > len(maxlenstr): #if current cub-string's length is greater than max one,
maxlenstr = curlenstr; #take current one as max one.
print("Longest substring in alphabetical order is:", maxlenstr)
s = input("insert some string: ")
start = 0
end = 0
temp = ""
while end+1 <len(s):
while end+1 <len(s) and s[end+1] >= s[end]:
end += 1
if len(s[start:end+1]) > len(temp):
temp = s[start:end+1]
end +=1
start = end
print("longest ordered part is: "+temp)
I suppose this is problem set question for CS6.00.1x on EDX. Here is what I came up with.
s = raw_input("Enter the string: ")
longest_sub = ""
last_longest = ""
for i in range(len(s)):
if len(last_longest) > 0:
if last_longest[-1] <= s[i]:
last_longest += s[i]
else:
last_longest = s[i]
else:
last_longest = s[i]
if len(last_longest) > len(longest_sub):
longest_sub = last_longest
print(longest_sub)
I came up with this solution
def longest_sorted_string(s):
max_string = ''
for i in range(len(s)):
for j in range(i+1, len(s)+1):
string = s[i:j]
arr = list(string)
if sorted(string) == arr and len(max_string) < len(string):
max_string = string
return max_string
Assuming this is from Edx course:
till this question, we haven't taught anything about strings and their advanced operations in python
So, I would simply go through the looping and conditional statements
string ="" #taking a plain string to represent the then generated string
present ="" #the present/current longest string
for i in range(len(s)): #not len(s)-1 because that totally skips last value
j = i+1
if j>= len(s):
j=i #using s[i+1] simply throws an error of not having index
if s[i] <= s[j]: #comparing the now and next value
string += s[i] #concatinating string if above condition is satisied
elif len(string) != 0 and s[i] > s[j]: #don't want to lose the last value
string += s[i] #now since s[i] > s[j] #last one will be printed
if len(string) > len(present): #1 > 0 so from there we get to store many values
present = string #swapping to largest string
string = ""
if len(string) > len(present): #to swap from if statement
present = string
if present == s[len(s)-1]: #if no alphabet is in order then first one is to be the output
present = s[0]
print('Longest substring in alphabetical order is:' + present)
I agree with #Abhijit about the power of itertools.groupby() but I took a simpler approach to (ab)using it and avoided the boundary case problems:
from itertools import groupby
LENGTH, LETTERS = 0, 1
def longest_sorted(string):
longest_length, longest_letters = 0, []
key, previous_letter = 0, chr(0)
def keyfunc(letter):
nonlocal key, previous_letter
if letter < previous_letter:
key += 1
previous_letter = letter
return key
for _, group in groupby(string, keyfunc):
letters = list(group)
length = len(letters)
if length > longest_length:
longest_length, longest_letters = length, letters
return ''.join(longest_letters)
print(longest_sorted('hixwluvyhzzzdgd'))
print(longest_sorted('eseoojlsuai'))
print(longest_sorted('drurotsxjehlwfwgygygxz'))
print(longest_sorted('abcdefghijklmnopqrstuvwxyz'))
OUTPUT
> python3 test.py
luvy
jlsu
ehlw
abcdefghijklmnopqrstuvwxyz
>
s = 'azcbobobegghakl'
i=1
subs=s[0]
subs2=s[0]
while(i<len(s)):
j=i
while(j<len(s)):
if(s[j]>=s[j-1]):
subs+=s[j]
j+=1
else:
subs=subs.replace(subs[:len(subs)],s[i])
break
if(len(subs)>len(subs2)):
subs2=subs2.replace(subs2[:len(subs2)], subs[:len(subs)])
subs=subs.replace(subs[:len(subs)],s[i])
i+=1
print("Longest substring in alphabetical order is:",subs2)
s = 'gkuencgybsbezzilbfg'
x = s.lower()
y = ''
z = [] #creating an empty listing which will get filled
for i in range(0,len(x)):
if i == len(x)-1:
y = y + str(x[i])
z.append(y)
break
a = x[i] <= x[i+1]
if a == True:
y = y + str(x[i])
else:
y = y + str(x[i])
z.append(y) # fill the list
y = ''
# search of 1st longest string
L = len(max(z,key=len)) # key=len takes length in consideration
for i in range(0,len(z)):
a = len(z[i])
if a == L:
print 'Longest substring in alphabetical order is:' + str(z[i])
break
first_seq=s[0]
break_seq=s[0]
current = s[0]
for i in range(0,len(s)-1):
if s[i]<=s[i+1]:
first_seq = first_seq + s[i+1]
if len(first_seq) > len(current):
current = first_seq
else:
first_seq = s[i+1]
break_seq = first_seq
print("Longest substring in alphabetical order is: ", current)

Categories

Resources