Reverse only vowels in a string - python

Given a string, I want to reverse only the vowels and leave the remaining string as it is. If input is fisherman output should be fashermin. I tried the following code:
a=input()
l=[]
for i in a:
if i in 'aeiou':
l.append(i)
siz=len(l)-1
for j in range(siz,-1,-1):
for k in a:
if k in 'aeiou':
a.replace(k,'l')
print(a)
What changes should be made in this code to get the desired output?

It is a little easier to turn your word into a list of letters and back:
a=input('Enter word: ')
l=[]
for i in a:
if i in 'aeiou':
l.append(i)
letters = list(a)
for i in range(len(letters)):
if letters[i] in 'aeiou':
letters[i] = l.pop(-1)
print(''.join(letters))

You have few logical mistakes in the code.
You need to save the o/p of .replace function in another string
a= a.replace(k,'l')
'l' is a string. I am sure it was list access that you were going for, so the correct syntax is: a= a.replace(k,l[j])
When replacing if you use the same string(string 'a' in your case), it will lead to all vowels getting replaced by a same vowel.
Using the same variable names, you used, following is one of the correct ways to do it:
a=input()
l=""
for i in a:
if i in 'aeiouAEIOU':
l+=i
new_a = ""
for k in a:
if k in "aeiouAEIOU":
new_a += l[-1]
l = l[:-1]
else:
new_a += k
print(a)
print(new_a)

Here is a piece of code that I have worked on that is the same question.
Write a program to reverse only the vowels in the string.
Example:
Input:
India
Output:
andiI
def revv(word):
a = ''
b = ''
for x in word:
if x in 'aeiouAEIOU':
a = a+x
b = b+'-'
else:
b = b+x
c = ''
d = 0
a = a[::-1]
for x in b:
if x=='-':
c = c+a[d]
d = d+1
else:
c = c+x
print(c)
revv('India')
Output:
andiI

This must work. First found vowels and and indexes of the vowels also you need to store it in a variable. After that you can reverse it easly buy going backword.
a = "fisherman"
def isVowel(c):
if c == "a" or c == "e" or c == "u" or c == "i" or c == "o":
return True
return False
def reverseOnlyVowels(string):
indexes = []
chars = []
# get vowels and indexes
for index, i in enumerate(list(string)):
if isVowel(i):
indexes.append(index)
chars.append(i)
# reverse vowels
stringList = list(string)
index1 = 0
for i, index in zip(chars[::-1], indexes[::-1]):
stringList[index] = chars[index1]
index1 += 1
return "".join(stringList)
print(reverseOnlyVowels(a))

Related

Delete repeated vowels in string

Here is my code:
def del_rep_vow(s):
'''
>>> del_rep_vow('adaptation')
'adpttion'
>>> del_rep_vow('repetitions')
'reptitons'
>>> del_rep_vow('kingkong')
'kingkong'
>>> del_rep_vow('aeiouaeiou')
'aeiou'
'''
final_list = []
for i in s:
if i not in final_list:
final_list.append(i)
return ''.join(final_list)
if __name__ == "__main__":
import doctest
doctest.testmod(verbose=True)
I don't know how to make the restriction that only repeated vowels have to be deleted once they are in the list. Any help will be very welcome.
Output of 'adaptation' must be 'adpttion', for example.
You should maintain a Python set of vowel characters already seen. For each new encountered letter as you walk down the string, only append a vowel if it is not in the set.
def del_rep_vow(s):
vowels_seen = set()
final_list = []
for i in s:
if i in ['a', 'e', 'i', 'o', 'u']:
if i not in vowels_seen:
final_list.append(i)
vowels_seen.add(i)
else:
final_list.append(i)
return ''.join(final_list)
print(del_rep_vow('adaptation')) # 'adpttion'
print(del_rep_vow('repetitions')) # 'reptitons'
print(del_rep_vow('kingkong')) # 'kingkong'
print(del_rep_vow('aeiouaeiou')) # 'aeiou'
I feel this is pretty concise:
def del_rep_vow(s):
for ch in 'eaiou':
if ch in s:
i = s.index(ch) + 1
s = s[:i] + s[i:].replace(ch, '')
return s
print(del_rep_vow('adaptation'))
print(del_rep_vow('repetitions'))
print(del_rep_vow('kingkong'))
print(del_rep_vow('aeiouaeiou'))
Result:
adpttion
reptitons
kingkong
aeiou
You could also keep your initial code, adding just a little condition to the test:
def del_rep_vow(s):
final_list = []
vowels = 'aeiou'
for i in s:
if i not in vowels or i not in final_list: # allowed consonants to be added every time
final_list.append(i)
return ''.join(final_list)
The str.partition method closely matches your need. It splits the string at the first occurrence of a separator and returns a 3-tuple containing the part before the separator, the separator itself or "" if not found, and the part after the separator. All that remains is to remove the vowel from the after-part.
def del_rep_vow(s):
for v in 'aeiou':
before, vowel, after = s.partition(v)
s = before + vowel + after.replace(v, '')
return s
print(del_rep_vow('adaptation')) # 'adpttion'
print(del_rep_vow('repetitions')) # 'reptitons'
print(del_rep_vow('kingkong')) # 'kingkong'
print(del_rep_vow('aeiouaeiou')) # 'aeiou'
You can maintain 2 lists of letters: one for the vowels you have seen so far, and other for the remaining letters in the string.
vowels = []
remaining = []
for c in s:
if c in 'aeiou':
if c in vowels:
continue
vowels.append(c)
remaining.append(c)
Here's another approach
def del_repts(x):
vowels = 'aeiou'
foundVowels = ''
rslt = ''
for c in x:
if c in vowels:
if c not in foundVowels:
rslt += c
foundVowels += c
else:
rslt += c
return rslt
inl = ['adaptation', 'repetitions', 'kingkong', 'aeiouaeiou']
for itm in inl:
print(f'{itm}\t->\t{del_repts(itm)}' )
Yields:
adaptation -> adpttion
repetitions -> reptitons
kingkong -> kingkong
aeiouaeiou -> aeiou
recursive solution:
def del_rep_vow(s):
return del_rep_vow(s[:-1]) + ('' if s[-1] in 'aeiou' and s[-1] in s[:-1] else s[-1]) if s else ''
del_rep_vow('repetitions') # reptitons'

How to capitalize a word in list without using python's in built methods?

I have tried the following , which gives me the output but i want output to be in list format :
for i, s in enumerate(st):
for j,ch in enumerate(s):
if j==0:
print(s[j].replace(s[j],s[j].upper()),end='')
else:
print(s[j].replace(s[j], s[j].lower()),end='')
Hope this helps.
stlist = []
stlist.append(st[0].upper())
for s in st[1:]:
stlist.append(s.lower())
print(stlist)
According to your example. Just use the above function on each element in list.
st=['RAnga','test']
new_st = []
for s in st:
new_s = ''
new_s += s[0].upper()
for c in s[1:]:
new_s += c.lower()
new_st.append(new_s)
print(new_st)

Sort non repeated characters and then repeated ones?

I am doing the following programming exercise: Return String As Sorted Blocks. The statement is:
Task
You will receive a string consisting of lowercase letters, uppercase
letters and digits as input. Your task is to return this string as
blocks separated by dashes ("-"). The elements of a block should be
sorted with respect to the hierarchy listed below, and each block
cannot contain multiple instances of the same character.
The hierarchy is:
lowercase letters (a - z), in alphabetic order
uppercase letters (A - Z), in alphabetic order
digits (0 - 9), in ascending order
Examples
"21AxBz" -> "xzAB12" - since input does not contain repeating characters, you only need 1 block
"abacad" -> "abcd-a-a" - character "a" repeats 3 times, thus 3 blocks are needed
"" -> "" - an empty input should result in an empty output
Good luck!
I have written the following code:
def blocks(s):
print("s: "+s)
lowers = []
uppers = []
digits = []
for c in s:
if c.islower():
lowers.append(c)
if c.isupper():
uppers.append(c)
if c.isdigit():
digits.append(c)
lowers.sort()
uppers.sort()
digits.sort()
print("lowers: ")
print(lowers)
print("uppers: ")
print(uppers)
print("digits: ")
print(digits)
result = ""
sorted = lowers+uppers+digits
removedLetters = 0
needsNextBlock = False
nextBlock = "-"
while len(sorted) > 0:
for i, c in enumerate(sorted):
print(i, c)
print("result: ")
print(result)
if c not in result:
result += c
print("we want to delete: ")
print(c)
sorted = sorted[0:i-removedLetters] + sorted[i+1-removedLetters:]
removedLetters += 1
print("new sorted: ")
print(sorted)
else:
if c not in nextBlock:
needsNextBlock = True
nextBlock += c
sorted = sorted[0:i-removedLetters] + sorted[i+1-removedLetters:]
removedLetters += 1
print("new sorted: ")
print(sorted)
if needsNextBlock:
result += nextBlock
needsNextBlock = False
nextBlock = "-"
return result
And there is a bug, because of when we have the following test:
Test.assert_equals(blocks("abacad"), "abcd-a-a")
The trace is:
s: abacad
lowers:
['a', 'a', 'a', 'b', 'c', 'd']
uppers:
[]
digits:
[]
0 a
result:
we want to delete:
a
new sorted:
['a', 'a', 'b', 'c', 'd']
1 a
result:
a
new sorted:
['a', 'b', 'c', 'd']
2 a
result:
a
3 b
result:
a
we want to delete:
b
new sorted:
['a', 'c', 'd']
4 c
result:
ab
we want to delete:
c
new sorted:
['a', 'd']
5 d
result:
abc
we want to delete:
d
new sorted:
['a']
0 a
result:
abcd-a
new sorted:
['a']
0 a
result:
abcd-a-a
new sorted:
['a']
0 a
result:
abcd-a-a-a
new sorted:
['a']
0 a
result:
abcd-a-a-a-a
new sorted:
['a']
0 a
(infinite loop)
So as we see the difficulty is created when we execute:
sorted = sorted[0:i-removedLetters] + sorted[i+1-removedLetters:]
removedLetters += 1
Because we have previously passed over the repeated letter, in this case 'a', but we have not counted it, so the calculus for the new sorted substring keeps being the same.
I tried a naive approach:
def blocks(s):
print("\n\n\ns: "+s)
lowers = []
uppers = []
digits = []
for c in s:
if c.islower():
lowers.append(c)
if c.isupper():
uppers.append(c)
if c.isdigit():
digits.append(c)
lowers.sort()
uppers.sort()
digits.sort()
print("lowers: ")
print(lowers)
print("uppers: ")
print(uppers)
print("digits: ")
print(digits)
result = ""
sorted = lowers+uppers+digits
removedLetters = 0
needsNextBlock = False
nextBlock = "-"
while len(sorted) > 0:
initialIterationLength = len(sorted)
for i, c in enumerate(sorted):
print(i, c)
print("result: ")
print(result)
if c not in result:
result += c
print("we want to delete: ")
print(c)
sorted = sorted[0:i-removedLetters] + sorted[i+1-removedLetters:]
removedLetters += 1
print("new sorted: ")
print(sorted)
else:
if c not in nextBlock:
needsNextBlock = True
nextBlock += c
sorted = sorted[0:i-removedLetters] + sorted[i+1-removedLetters:]
removedLetters += 1
if initialIterationLength == len(sorted):
sorted = []
print("new sorted: ")
print(sorted)
if needsNextBlock:
result += nextBlock
needsNextBlock = False
nextBlock = "-"
return result
As you see, I added when we start the while loop the sentence: initialIterationLength = len(sorted) and inside the loop, in the if condition:
if initialIterationLength == len(sorted):
sorted = []
It does work for the test being discussed, however for larger inputs it won't work.
For example when input is:
ZrXx2VpVJMgPs54SwwxSophZEWvwKUxzqNxaxlgY0T
Our result is:
aghlopqrsvwxzEJKMNPSTUVWXYZ0245-gpwxSVZ-wx
Expected is:
aghlopqrsvwxzEJKMNPSTUVWXYZ0245-gpwxSVZ-wx-x-x
I think there should be a better algorithm.
I have read:
How do I get a substring of a string in Python?
Does Python have a string 'contains' substring method?
Accessing the index in 'for' loops?
How do I concatenate two lists in Python?
How can I check if a string represents an int, without using try/except?
Check if string is upper, lower, or mixed case in Python
Iterating each character in a string using Python
How to detect lowercase letters in Python?
How could we sort non repeated characters and then repeated ones?
You could use a Counter to keep track of the iterations you need according to the repeated digits.
import string
from collections import Counter
ORDER = {s:i for i, s in enumerate(string.ascii_letters + string.digits)}
def my_sorted(s):
c = Counter(s)
res = []
it = 1
to_sort = set(c)
while len(to_sort) > 0:
res.append(sorted(to_sort ,key=lambda x:ORDER[x]))
to_sort = [k for k in c if c[k] > it]
it+=1
return "-".join(["".join(l) for l in res])
Example:
>>> s="ZrXx2VpVJMgPs54SwwxSophZEWvwKUxzqNxaxlgY0T"
>>> my_sorted(s)
aghlopqrsvwxzEJKMNPSTUVWXYZ0245-gpwxSVZ-gpwxSVZ-wx-x-x
Stealing from #abc's answer...
import string
from collections import Counter
ORDER = {s:i for i, s in enumerate(string.ascii_letters + string.digits)}
def my_sorted(s):
c = Counter(s)
res = []
while c:
res.append(''.join(sorted(c, key=ORDER.get)))
c -= Counter(set(c))
return "-".join(res)
Example:
>>> s = "ZrXx2VpVJMgPs54SwwxSophZEWvwKUxzqNxaxlgY0T"
>>> my_sorted(s)
'aghlopqrsvwxzEJKMNPSTUVWXYZ0245-gpwxSVZ-wx-x-x'
Still stealing #abc's setup, but completely different solution. I append the needed number of dashes and then sort everything based on 1) the how-many-eth occurrence a character is and 2) the aA0- order.
import string
from collections import Counter
ORDER = {s:i for i, s in enumerate(string.ascii_letters + string.digits + '-')}
def my_sorted(s):
return ''.join(sorted(s + '-' * (max(Counter(s).values()) - 1),
key=lambda c, ctr=Counter(): (ctr.update(c) or ctr[c], ORDER[c])))
Example:
>>> s = "ZrXx2VpVJMgPs54SwwxSophZEWvwKUxzqNxaxlgY0T"
>>> my_sorted(s)
'aghlopqrsvwxzEJKMNPSTUVWXYZ0245-gpwxSVZ-wx-x-x'

How to create a list from results from a given list within a for loop?

I am doing googles python class. And came across this problem:
# A. match_ends
# Given a list of strings, return the count of the number of
# strings where the string length is 2 or more and the first
# and last chars of the string are the same.
# Note: python does not have a ++ operator, but += works.
I tried different approaches, but cant seem to get it to work. This is what i got now:
def match_ends(words):
words=sorted(words, key=len)
for i in words:
if len(i)<2:
print(i)
words=words[1:]
print(words)
for i in words:
if i[0:2]==i[-2:]:
x=[]
x.append[i]
How is this done?
Easy to accomplish using sum and a generator expression:
def match_ends(words):
return sum(len(word) >= 2 and word[0] == word[-1] for word in words)
You could simply do this:
def match_ends(words):
count = 0
for word in words:
if len(word) >= 2 and word[0] == word[-1]:
count += 1
return count
A more pythonic solution might be
def func(s):
return len(s) >= 2 and s[0] == s[-1]
str_list = ['applea', 'b', 'cardc']
filtered_list = [s for s in str_list if (len(s) >= 2 and s[0] == s[-1])]
# or
filtered_list = list(filter(func, str_list))
count = len(filtered_list)
pretty much the same as previous answers, but lambda
match_ends = lambda ws: sum(1 for w in ws if len(w)>1 and w[0] == w[-1])
or 'expanded' form
match_ends = lambda words: sum(1 for word in words if len(word)>1 and word[0] == word[-1])

check if string is in abc order

So the function should count the number of times the letters in uppercase are out of abc order.
>>> abc('ABBZHDL')
2
Above, z and d are out of order.
>>> abc('ABCD')
0
>>> abc('DCBA')
4
My code:
def abc(check):
order=ABCDEFGHIJKLMNOPQRSTUVWXYZ
for c in check:
if check != order:
#then I get stuck here
Pointers?
The question is ill-defined. One solution to a nearby question would be using the builtin sorted():
def abc(s):
count = 0
s = ''.join(i for i in s if i.isupper())
l = sorted(s)
for i,c in enumerate(s):
if l[i] != c:
count += 1
return count
It counts all of the places where the alphabetized string does not match the original.
def abc(check):
last = ''
count = 0
for letter in check:
if not letter.isupper():
continue
if letter < last:
count += 1
last = letter
return count
import string
a = 'acbdefr'
b = 'abdcfe'
assert ''.join(sorted(b)) in string.ascii_letters
assert ''.join(sorted(a)) in string.ascii_letters #should fail
Its really simple everyone seems to be overcomplicating it somewhat?

Categories

Resources