Working on a homework question that requires us to make a function where all the vowels in a string are reversed. example: This Is So Fun would return Thus Os Si Fin. Just can't figure out how to make the function detect the where the uppercase letters are to convert them into lowercase and vice versa. Right now the function outputs Thus os SI Fin
def f(word):
vowels = "aeiouAEIOU"
string = list(word)
i = 0
j = len(word)-1
while i < j:
if string[i].lower() not in vowels:
i += 1
elif string[j].lower() not in vowels:
j -= 1
else:
string[i], string[j] = string[j], string[i]
i += 1
j -= 1
return "".join(string)
If you make a small function that takes two characters and returns each with the other's case you can simply wrap your assignment in that:
def swapCase(c1, c2):
return (
c1.upper() if c2.isupper() else c1.lower(),
c2.upper() if c1.isupper() else c2.lower()
)
def f(word):
vowels = "aeiouAEIOU"
string = list(word)
i = 0
j = len(word)-1
while i < j:
if string[i].lower() not in vowels:
i += 1
elif string[j].lower() not in vowels:
j -= 1
else:
string[i], string[j] = swapCase(string[j], string[i])
i += 1
j -= 1
return "".join(string)
f("This Is So Fun")
# 'Thus Os Si Fin'
One approach can be to check the two letters that you are replacing. If their case is the same, then you don't need to do anything, but if their case is not the same, you would switch their case before you switch the letters.
I am not sure if you need it, but this approach is a bit more flexible than #Madivad's answer as it allows you to pass strings with capitalizations anywhere within the string such as This Is SoO FunIE -> Thes Is SuO FonII
An easy way to do it is to check the capitalization with str.isupper() method and then do the reversal with an if/else case
if string[i].isupper() != string[j].isupper():
if string[i].isupper():
string[j], string[i] = string[j].upper(), string[i].lower()
else:
string[j], string[i] = string[j].lower(), string[i].upper()
Finalyl you would incorporate this snippet it in your code just above your string replacement:
def f(word):
vowels = "aeiouAEIOU"
string = list(word)
i = 0
j = len(word)-1
while i < j:
if string[i].lower() not in vowels:
i += 1
elif string[j].lower() not in vowels:
j -= 1
else:
if string[i].isupper() != string[j].isupper():
if string[i].isupper():
string[j], string[i] = string[j].upper(), string[i].lower()
else:
string[j], string[i] = string[j].lower(), string[i].upper()
string[i], string[j] = string[j], string[i]
i += 1
j -= 1
return "".join(string)
'''
Try the below approach:
The idea is as below:
First get the list of vowels into a list
Next, try to interchange them
Now, iterate through the input and change the vowels while checking the original case of the vowels in the input
Note: I have not done a complete a testing for all cases. You will have to probably check and handle it yourself.
def f(word):
vowels = "aeiouAEIOU"
vowels_in_word = [x for x in word if x in vowels]
word_list = list(word)
print("Vowels in word in order = %s" %(vowels_in_word))
i = 0
j = len(vowels_in_word)-1
while i <= j:
vowels_in_word[i], vowels_in_word[j] = vowels_in_word[j], vowels_in_word[i]
i += 1
j -= 1
print("Changed Vowels = %s" %(vowels_in_word))
i = 0
j = 0
for x in word_list:
if x in vowels:
if x.islower():
word_list[i] = vowels_in_word[j].lower()
else:
word_list[i] = vowels_in_word[j].upper()
j += 1
i += 1
result_str = ''.join(x for x in word_list)
print("Result Str = %s" %(result_str))
f("This Is So Fun")
Output:
Vowels in word in order = ['i', 'I', 'o', 'u']
Changed Vowels = ['u', 'o', 'I', 'i']
Result Str = Thus Os Si Fin
How I would/did approach it
go through, grab the vowels
reiterate over the string, rebuilding it with a reversed vowel list
when inserting a vowel, check the case of the original character in that position
Edit: since everyone is providing a solution, I thought I too would provide a solution.
This is how I achieved the same goal:
Iterate through the string and grab the vowels
Go through the string a second time, swapping out the reversed vowels
str="This Is So Fun"
print(str)
vowels=[]
for letter in str:
if letter.lower() in "aeiou":
vowels.append(letter.lower())
out = ""
for letter in str:
if letter.lower() in "aeiou":
if letter.isupper():
out += vowels.pop().upper()
else:
out += vowels.pop().lower()
else:
out += letter
print(out)
Related
I want to count number of same letter at beginning between two words (letter by letter) until there's one different and return who has the most same letter.
This is my code :
def same(word, liste):
letter = 0
dico = dict()
for i in liste:
while word[letter] == i[letter]:
letter += 1;
dico[i] = letter;
letter = 0;
same = max(dico, key=dico.get)
return same
But i get always this error of string index out of range, I've tried with much way but nothing
while word[letter] == i[letter]:
IndexError: string index out of range
In input :
same('hello',['hi,'hell','helo'])
Output:
'hell'
Thanks
I would just use a list comprehension along with basic substring logic:
def same(word, liste):
return max([x for x in liste if x in word], key=len)
print(same('hello',['hi','hell','helo'])) # hell
you can't go out of range in your while
verify the length of your word before word[letter] == i[letter]
while letter < len(word) and letter < len(i) and word[letter] == i[letter]:
gives you :
def same(word, liste):
letter = 0
dico = dict()
for i in liste:
while letter < len(word) and letter < len(i) and word[letter] == i[letter]:
letter += 1;
dico[i] = letter;
letter = 0;
same = max(dico, key=dico.get)
return same
print(same('blablabla',['blaze','bli']))
----------
>>> blaze
A combination of zip, sum and max should give you the result -
def same(word, liste):
pairs = [zip(word, x) for x in liste]
match_len = [sum([x == y for x, y in pair]) for pair in pairs]
return lst[match_len.index(max(match_len))]
Yet an other solution:
def same(word, liste):
def get_score(word, other):
for i, (l1, l2) in enumerate(zip(word, other)):
if l1 != l2:
break
return i
scores = {other:get_score(word, other) for other in liste}
return max(scores, key=scores.get)
In this case, I define the function get_score to count the number of common letters in a pair of words. I am sure to not run in IndexError because of the zip that makes an iterator over the 2 words.
Then I just did the same as you to get the word associated with the greatest score.
My teacher challenged me of finding a way to count the occurences of the word "bob" in any random string variable without str.count(). So I did,
a = "dfjgnsdfgnbobobeob bob"
compteurDeBob = 0
for i in range (len(a) - 1):
if a[i] == "b":
if a[i+1] == "o":
if a[i+2] == "b":
compteurDeBob += 1
print(compteurDeBob)
but I wanted to find a way to do that with a word of any length as shown below, but I have no clue on how to do that...
a = input("random string: ")
word = input("Wanted word: ")
compteurDeBob = 0
for i in range (len(a)-1):
#... i don't know...
print(compteurDeBob)
a = input("random string: ")
word = input("Wanted word: ")
count = 0
for i in range(len(a)-len(word)):
if a[i:i+len(word)] == word:
count += 1
print(count)
If you want your search to be case-insensitive, then you can use lower() function:
a = input("random string: ").lower()
word = input("Wanted word: ").lower()
count = 0
for i in range(len(a)):
if a[i:i+len(word)] == word:
count += 1
print(count)
For the user input
Hi Bob. This is bob
the first approach will output 1 and the second approach will output 2
To count all overlapping occurrences (like in your example) you could just slice the string in a loop:
a = input("random string: ")
word = input("Wanted word: ")
cnt = 0
for i in range(len(a)-len(word)+1):
if a[i:i+len(word)] == word:
cnt += 1
print(cnt)
You can use string slicing. One way to adapt your code:
a = 'dfjgnsdfgnbobobeob bob'
counter = 0
value = 'bob'
chars = len(value)
for i in range(len(a) - chars + 1):
if a[i: i + chars] == value:
counter += 1
A more succinct way of writing this is possible via sum and a generator expression:
counter = sum(a[i: i + chars] == value for i in range(len(a) - chars + 1))
This works because bool is a subclass of int in Python, i.e. True / False values are considered 1 and 0 respectively.
Note str.count won't work here, as it only counts non-overlapping matches. You could utilise str.find if built-ins are allowed.
The fastest way to calculate overlapping matches is the Knuth-Morris-Pratt algorithm [wiki] which runs in O(m+n) with m the string to match, and n the size of the string.
The algorithm first builds a lookup table that acts more or less as the description of a finite state machine (FSM). First we construct such table with:
def build_kmp_table(word):
t = [-1] * (len(word)+1)
cnd = 0
for pos in range(1, len(word)):
if word[pos] == word[cnd]:
t[pos] = t[cnd]
else:
t[pos] = cnd
cnd = t[cnd]
while cnd >= 0 and word[pos] != word[cnd]:
cnd = t[cnd]
cnd += 1
t[len(word)] = cnd
return t
Then we can count with:
def count_kmp(string, word):
n = 0
wn = len(word)
t = build_kmp_table(word)
k = 0
j = 0
while j < len(string):
if string[j] == word[k]:
k += 1
j += 1
if k >= len(word):
n += 1
k = t[k]
else:
k = t[k]
if k < 0:
k += 1
j += 1
return n
The above counts overlapping instances in linear time in the string to be searched, which was an improvements of the "slicing" approach that was earlier used, that works in O(m×n).
I'm trying to create a function to evaluate if contains at least three vowels consecutively.
I've tried so far:
( I don't know how to evaluate if they are consecutive)
any ideas?
def isConsecutive(word):
# initialize vowel count
vCounter = 0
for letter in word:
if letter == isVowel(word):
vCounter += 1
else:
vCounter = 0
if vCounter < 3:
return False
return True
Helper function
def isVowel(char):
return len(char) == 1 and char.lower() in 'aeiou'
The check, whether you have reached the third vovel in sequence, should be right after the vCounter += 1. If there are three vovels: return true.
Also, the isVowel check should be applied to the letter, not the whole word.
def isVowel(char):
return char.lower() in 'aeiou'
def isConsecutive(word):
# initialize vowel count
vCounter = 0
for letter in word:
if isVowel(letter): # <= check if the letter is a vowel
vCounter += 1
if vCounter >= 3: # <= do the check right here
return True
else:
vCounter = 0
return False # <= if we did not find three vovels in the loop, then there is none
print "hello: " + str(isConsecutive("hello"))
print "heeello: " + str(isConsecutive("heeello"))
print "hellooo: " + str(isConsecutive("hellooo"))
Give it a try online: DEMO
You can do this also with two list comprehensions:
a list of booleans, if the characters in a word are vowels
a list of booleans, if there are three consecutive True values in the first list
.
def three_consecutive_vowels(s):
is_vow = [c.lower() in 'aeiou' for c in s]
three_cons = [all(is_vow[i:i+2]) for i in range(len(is_vow) - 2)]
return any(three_cons)
Test:
words = ['hellO', 'heIah', 'aAarrgh']
for w in words:
print(three_consecutive_vowels(w))
False
True
True
def myfunc(word):
result = ""
index = 0
for letter in word:
if index % 2 == 0:
result += letter.lower()
else:
result += letter.upper()
return result
index +=1
I am trying to return a matching string where every even letter is uppercase and every odd letter is lowercase. But the code doesn't show this exact result, any solution?
The problem is that you're only incrementing index after the loop, rather than each time through it. So, inside the loop, it's always 0. The smallest fix is:
def myfunc(word):
result = ""
index = 0
for letter in word:
if index % 2 == 0:
result += letter.lower()
else:
result += letter.upper()
index += 1
return result
But this kind of mistake is very easy to make (and sometimes not as easy as this to debug)—which is exactly why Python has nice tools like enumerate, that make it impossible to get wrong:
def myfunc(word):
result = ""
for index, letter in enumerate(word):
if index % 2 == 0:
result += letter.lower()
else:
result += letter.upper()
return result
People, including myself, have already pointed out your programming error. Here is an alternative one-liner solution to your problem using a generator expression and a ternary conditional operator:
def myfunc(word):
return "".join(w.upper() if i%2 else w.lower() for i,w in enumerate(word))
enumerate will return a tuple of the form (index, value) for each item in the iterable. In this case, the iterable is the string word.
At each step in the iteration, we check to see if the index i is odd.
i%2 will return 0 for even numbers and the if statement will evaluate to False.
Likewise, it will evaluate to True for odd numbers.
Respectively, we call lower() and upper() on the current character w.
Finally we use str.join to concatenate all the individual letters back together. Here we join the characters using an "" with is the empty string.
The problem was with how you were incrementing. You only set up your index to increment inside the "Else" block of your code. It was missing from the "If" block. As such as soon as you entered the "If" block you would be stuck there.
def myfunc(string):
result = ""
index = 0
for letter in string:
if index % 2 == 0:
result += letter.upper()
index += 1
else:
result += letter.lower()
index += 1
return result
def myfunc(word):
result = ""
for index, letter in enumerate(word):
if index % 2 == 0:
result += letter.lower()
else:
result += letter.upper()
return result
this worked for me.
Also it is much easier to understand the above block of code if you understand the enumerate function well
def myfunc(word):
index = 0
result = ''
for letter in word:
if index % 2 == 0:
result += letter.lower()
else:
result += letter.upper()
index += 1
print result
You weren't increment your index in the correct spot ;)
If you execute myfunc(word) it will print hElLo
def gonna(st) :
a = []
Index = 0
for index, c in enumerate(st) :
if index ℅ 2 == 0:
a.append(c.upper())
Index = Index + 1
else:
a.append(c.lower())
Index = Index + 1
return a
def myfunc(a):
result=""
for x in range(0,len(a)):
if x%2==0:
result=result+a[x].upper()
else:
result=result+a[x].lower()
return result
def myfunc(word):
z=list(word)
x=[]
y=[]
new_list=[]
str=""
for a in z:
x+=[a]
if len(x)==2:
y+=[x]
x=[]
for i in y:
odd=i[0].lower()
even=i[1].upper()
new_list.append(odd)
new_list.append(even)
for el in new_list:
str+=el
return str
def myfunc(str):
# Create an empty string to append the values to
result = ''
# Iterate through the loop using the enumerate function on the string so that you can use the index and the letter at the same time.
for index,letter in enumerate(str):
if index %2 == 0:
result += letter.lower()
else:
result += letter.upper()
# Return the string after all the letters have been appended to the string
return result
More Simpler , which is made using all the basic conecpts of Python
def myfunc(string):
new_string=""
for items in range(len(string)): # help us to to know about the index
if items % 2 == 0:
new_string = new_string + string[items].upper()
else:
new_string = new_string + string[items].lower()
return new_string
result=myfunc("Draco")
print(result)
def myfunc(word):
index=0
result = ''
for letter in word:
if index%2==0:
result=result+letter.upper()
else:
result=result+letter.lower()
index+=1
return result
**
Heading
**
def myfunc(word):
result = ""
for index, letter in enumerate(word):
if index % 2 == 0:
result += letter.upper()
else:
result += letter.lower()
return result
First time programming ever... I'm trying to do this exercise to.. :
Write a program that prints the longest substring of s in which the letters occur in alphabetical order. For example, if s = 'azcbobobegghakl', then your program should print
Longest substring in alphabetical order is: beggh
I was here..before starting to freak out:
s = 'abcdezcbobobegghakl'
n = len(s)
x = 0
x += 1
lengh = s[x-1]
if s[x] >= s[x-1]:
lengh = lengh + s[x]
if s[x+1] < s[x]:
n = len(lengh)
if x > n:
break
print('Longest substring in alphabetical order is: ' + str(lengh))
I know this code is bad..I m trying to find substring in alphabetical order and is some way keep the longest one! I know could be normal, because I never programmed before but i feel really frustrated...any good idea/help??
First try to decompose your problem into little problems (do not optimize ! until your problem is solved), if you have learned about functions they are a good way to decompose execution flow into readable and understandable snippets.
An example to start would be :
def get_sequence_size(my_string, start):
# Your code here
return size_of_sequence
current_position = 0
while current_position < len(my_string):
# Your code here using get_sequence_size() function
The following code solves the problem using the reduce method:
solution = ''
def check(substr, char):
global solution
last_char = substr[-1]
substr = (substr + char) if char >= last_char else char
if len(substr) > len(solution):
solution = substr
return substr
def get_largest(s):
global solution
solution = ''
reduce(check, list(s))
return solution
def find_longest_substr(my_str):
# string var to hold the result
res = ""
# candidate for the longest sub-string
candidate = ""
# for each char in string
for char in my_str:
# if candidate is empty, just add the first char to it
if not candidate:
candidate += char
# if last char in candidate is "lower" than equal to current char, add char to candidate
elif candidate[-1] <= char:
candidate += char
# if candidate is longer than result, we found new longest sub-string
elif len(candidate) > len(res):
res= candidate
candidate = char
# reset candidate and add current char to it
else:
candidate = char
# last candidate is the longest, update result
if len(candidate) > len(res):
res= candidate
return res
def main():
str1 = "azcbobobegghaklbeggh"
longest = find_longest_substr(str1)
print longest
if __name__ == "__main__":
main()
These are all assuming you have a string (s) and are needing to find the longest substring in alphabetical order.
Option A
test = s[0] # seed with first letter in string s
best = '' # empty var for keeping track of longest sequence
for n in range(1, len(s)): # have s[0] so compare to s[1]
if len(test) > len(best):
best = test
if s[n] >= s[n-1]:
test = test + s[n] # add s[1] to s[0] if greater or equal
else: # if not, do one of these options
test = s[n]
print "Longest substring in alphabetical order is:", best
Option B
maxSub, currentSub, previousChar = '', '', ''
for char in s:
if char >= previousChar:
currentSub = currentSub + char
if len(currentSub) > len(maxSub):
maxSub = currentSub
else: currentSub = char
previousChar = char
print maxSub
Option C
matches = []
current = [s[0]]
for index, character in enumerate(s[1:]):
if character >= s[index]: current.append(character)
else:
matches.append(current)
current = [character]
print "".join(max(matches, key=len))
Option D
def longest_ascending(s):
matches = []
current = [s[0]]
for index, character in enumerate(s[1:]):
if character >= s[index]:
current.append(character)
else:
matches.append(current)
current = [character]
matches.append(current)
return "".join(max(matches, key=len))
print(longest_ascending(s))
def longest(s):
buff = ''
longest = ''
s += chr(255)
for i in range(len(s)-1):
buff += s[i]
if not s[i] < s[i+1]:
if len(buff) > len(longest):
longest = buff
buff = ''
if len(buff) > len(longest):
longest = buff
return longest