Counting the Vowels at the End of a Word - python

Write a function named vowelEndings that takes a string, text, as a parameter.
The function vowelEndings returns a dictionary d in which the keys are all the vowels that are the last letter of some word in text. The letters a, e, i, o and u are vowels. No other letter is a vowel. The value corresponding to each key in d is a list of all the words ending with that vowel. No word should appear more than once in a given list. All of the letters in text are lower case.
The following is an example of correct output:
>>> t = 'today you are you there is no one alive who is you-er than you'
>>> vowelEndings(t)
{'u': ['you'], 'o': ['no', 'who'], 'e': ['are', 'there', 'one', 'alive']}
This is what I have so far:
def vowelEndings(text):
vowels = 'aeiouAEIOU'
vowelCount = 0
words = text.split()
for word in words:
if word[0] in vowels:
vowelCount += 1
return vowelCount
t = 'today you are you there is no one alive who is you-er than you'
print(vowelEndings(t))
Output:
5
What is doing is counting the vowels of the beginning of each word but it should be counting the vowels of the end of each word. Also, it should print out the vowel and the word which the vowel is referring to like in the question. I need help with that.

You are close. The missing aspects are:
To extract the last letter, use word[-1].
You need to create a dictionary with vowel keys.
The dictionary values should be set to avoid duplicates.
The classic Python solution is to use collections.defaultdict:
from collections import defaultdict
t = 'today you are you there is no one alive who is you-er than you'
def vowelEndings(text):
vowels = set('aeiou')
d = defaultdict(set)
for word in text.split():
final = word[-1]
if final in vowels:
d[final].add(word)
return d
print(vowelEndings(t))
defaultdict(set,
{'e': {'alive', 'are', 'one', 'there'},
'o': {'no', 'who'},
'u': {'you'}})

Related

Exclude words from a list that contain one or more characters from another list python

I have a list as an input which contains words, these words sometimes contain non-ascii letter characters, I need to filter out the entire word if they contain letters that are not in the ascii list.
So the if the input is:
words = ['Hello', 'my','dear', 'de7ar', 'Fri?ends', 'Friends']
I need the Output:
['Hello', 'my', 'dear', Friends']
words = ['Hello', 'my','dear', 'de7ar', 'Fri?ends', 'Friends']
al = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
ascii_letters = [char for char in al]
filtered_words=[]
I tried it with this:
for el in words:
try:
words in ascii_letters
except FALSE:
filtered_words.append(el)
and this
filtered words = [ele for ele in words if all(ch not in ele for ch in ascii_letters)]
but both of them do not result in what I need - I do understand why but since I have only been learning python for a week I fail to adjust them to make them do what I want them to, maybe someone knows how to handle this (without using any libraries)?
Thanks
You could check whether your alphabet is a superset of the words:
>>> [*filter(set(al).issuperset, words)]
['Hello', 'my', 'dear', 'Friends']
Btw, better don't hardcode that alphabet (I've seen quite a few people do that and forget letters) but import it:
from string import ascii_letters as al
You need to iterate trough the words in the words list to check whether all letters are ion ASCII or you can use the all() function:
words = ['Hello', 'my','dear', 'de7ar', 'Fri?ends', 'Friends']
al = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
ascii_letters = [char for char in al]
out = []
for word in words:
not_in_ascii = False
for letter in word:
if letter not in ascii_letters:
not_in_ascii = True
if not_in_ascii:
continue
out.append(word)
It is also possible with list comprehension and all() as you tried:
out = [word for word in words if all([letter in ascii_letters for letter in word])]
[i for i in words if i.isalpha()]
Result:
['Hello', 'my', 'dear', 'Friends']

Efficient and fastest way to search in a list of strings

The following function return the number of words from a list that contain the exact same characters as the word entered. The order of the characters in the words is not important. However, say there is a list that contain millions of words. What is the most efficient and fastest way to perform this search?
Example:
words_list = ['yek','lion','eky','ekky','kkey','opt'];
if we were to match the word "key" with the words in the list, the function only return "yek" and "eky" since they share the same exact characters with "key" regardless of the order.
Below is the function I wrote
def find_a4(words_list, word):
# all possible permutations of the word that we are looking for
# it's a set of words
word_permutations = set([''.join(p) for p in permutations(word)])
word_size = len(word)
count = 0
for word in word_list:
# in the case of word "key",
# we only accept words that have 3 characters
# and they are in the word_permutations
if len(word) == word_size and word in word_permutations:
count += 1
return count
A dictionary whose key is the sorted version of the word:
word_list = ['yek','lion','eky','ekky','kkey','opt']
from collections import defaultdict
word_index = defaultdict(set)
for word in word_list:
idx = tuple(sorted(word))
word_index[idx].add(word)
# word_index = {
# ('e', 'k', 'y'): {'yek', 'eky'},
# ('i', 'l', 'n', 'o'): {'lion'},
# ('e', 'k', 'k', 'y'): {'kkey', 'ekky'},
# ('o', 'p', 't'): {'opt'}
# }
Then for querying you would do:
def find_a4(word_index, word):
idx = tuple(sorted(word))
return len(word_index[idx])
Or if you need to return the actual words, change it to return word_index[idx].
Efficiency: querying runs in average in O(1) time.
For large string, you will have n! permutations to search. I will sort all the strings before comparison, this will be nlog(n), and will sort and compare only when lengths match -
def find_a4(words_list, word):
word = ''.join(sorted(word))
word_size = len(word)
count = 0
for word1 in words_list:
if len(word1) == word_size:
if word == ''.join(sorted(word1)):
count += 1
return count

Pattern matching in regex

I have below dictionary that I created in such a way that the key is the length of the values.
{4: {'lost', 'lust', 'list', 'last', 'lest', 'blue'}, 5: {'beryl'}, 8: {'blowlamp', 'blimbing', 'bluejays', 'jigsawed'}, 9: {'blistered', 'oospheres', 'blackcaps', 'blastular', 'blotchier', 'troweller'}, 10: {'blancmange', 'blackguard', 'volcanizes'}, 6: {'blague', 'blacks', 'blonde', 'blocks'}, 7: {'blawort', 'blinder', 'blender', 'blonder', 'blunder', 'blander'}}
I want to pull out a list of values in this dictionary in such a way that the vowel comes at the same place for 5 words like
[lost,lust,list,last,lest],[blinder,blender,blonder,blunder,blander]]
I am not having any idea on how to get the list in such a way. One way I thought could be through regex but on what basis do I match? The length of the words could be anything and vowel could be anywhere.
PS this is a codewars question. https://www.codewars.com/kata/vowel-alternations/train/python
My approach so far that I got the values with same length in a dictionary so that I can work on the values. I just have no idea how to work on the values.
It would be helpful if anyone can explain me what they are thinking and what is the best way to do this.
The rest of the code
mdict={}
rev_multidict = {}
for i in words:
for sublist in i:
mdict[sublist] = len(sublist)
for key, value in mdict.items():
rev_multidict.setdefault(value, set()).add(key)
for key,value in rev_multidict.items():
i = rev_multidict[key]
print(i)
You could check the first string for the location of the vowels and generate a regex string to match. Every char maps to either '[aeiou]' or '.' depending on if it's a vowel or not. Why you do with 'y' is up to you.
the following code is the start of one way of approaching it:
#!/usr/bin/python
import re
words = 'last lest best list '.split()
words1 = 'blander wigwam blunder slender'.split()
print("word list one: {}".format(words))
print('')
aoa = [re.split('[aeiou]', word) for word in words]
for item in aoa:
print(item)
print('\n')
print("word list two: {}".format(words1))
print('')
aoa1 = [re.split('[aeiou]', word) for word in words1]
for item in aoa1:
print(item)
the output is:
word list one: ['last', 'lest', 'best', 'list']
['l', 'st']
['l', 'st']
['b', 'st']
['l', 'st']
word list two: ['blander', 'wigwam', 'blunder', 'slender']
['bl', 'nd', 'r']
['w', 'gw', 'm']
['bl', 'nd', 'r']
['sl', 'nd', 'r']
The regex splits on vowels. If you look closely at the output of the split, you will notice that for the words that should match, the corresponding list index values are the same. Perhaps you can iterate over the lists and do a comparison.
That is left up to you...
Assuming you want to print out only if the output list contains 5 words:
text = {4: {'lost', 'lust', 'list', 'last', 'lest', 'blue'}, 5: {'beryl'}, 8: {'blowlamp', 'blimbing', 'bluejays', 'jigsawed'}, 9: {'blistered', 'oospheres', 'blackcaps', 'blastular', 'blotchier', 'troweller'}, 10: {'blancmange', 'blackguard', 'volcanizes'}, 6: {'blague', 'blacks', 'blonde', 'blocks'}, 7: {'blawort', 'blinder', 'blender', 'blonder', 'blunder', 'blander'}}
vowels = "aeiou"
for i in range(4,10):
words = text[i]
rep_idx = []
for word in words:
for letter in vowels:
if letter in word:
idx = word.index(letter)
if idx not in rep_idx:
word_list = []
for word in words:
if word[idx] in vowels:
word_list.append(word)
if len(word_list) == 5:
print ("{}, Vowel Index: {}".format(word_list, idx))
rep_idx.append(idx)
Output:
>>>
['lust', 'lest', 'list', 'lost', 'last'], Vowel Index: 1
['blonder', 'blender', 'blinder', 'blander', 'blunder'], Vowel Index: 5
['blistered', 'blackcaps', 'troweller', 'blastular', 'blotchier'], Vowel Index: 2
['blistered', 'troweller', 'oospheres', 'blastular', 'blotchier'], Vowel Index: 7
Ok, for the codewars Question (I've taken different approach than you, so I didn't use your code):
First you define a simple function changing all vowels for some (here a dollar sign) character:
from collections import Counter
def translate(word):
for ch in 'eyuioa':
if ch in word:
word=word.replace(ch,'$')
return word
Then you define a function, that takes list of words as an input (eg. ['last', 'lest', 'list', 'lost', 'lust'])) that counts occurences of each translated word, and find that translated word that occurs 5 times. Store it in a list and add a [None] just in case the list is empty (word not found), so that you don't get an error. Then simply print all words that meet a condition.
def find_solutions(input_list):
tuples_list = list(map(lambda x: (x,translate(x)),input_list))
counting = Counter(map(lambda x: x[1], tuples_list))
desired_pattern = [x for x,y in dict(counting).items() if y ==5] + [None]
return [x for x, y in tuples_list if y==desired_pattern[0]]
example:
find_solutions(['last', 'lest', 'list', 'lost', 'lust'])
This would be very robust approach, but it seems to work:
vowels = 'aeiou'
def find_solutions(words):
solutions = []
vowel_list = list(vowels)
cases = []
for word in words:
for i, l in enumerate(word):
if l in vowel_list:
c = list(word)
temp = []
for vowel in vowel_list:
c[i] = vowel
temp.append(''.join(c))
cases.append(temp)
for case in cases:
if all([item in words for item in case]):
if case not in solutions:
solutions.append(case)
return solutions

Use the method is_vowel

Write a value returning method, is vowel that returns true if a given characters is vowel otherwise returns false. Write a program that prompts the user to input a sequence of characters and outputs the number of vowels. Please help me to run this problem and what is the exact code
You can use char in "aeiouAEIOU" to determine if a character is a vowel, and use a list comprehension to produce a list containing only vowels, and find the number of vowels in the input string by finding the length of this list.
string=raw_input()
numOfVowels=len([char for char in string if char in "aeiouAEIOU"])
print(numOfVowels)
Input:
abcdefghijklmnopqrstuvwxyz
Output:
5
make a list of vowel letter to comapre letters in input that user enters:
vowel = ['a', 'e', 'i', 'o', 'u']
user_ask = input("enter a string to count the vowel:\t").casefold()
by using casefold method, you do not need to worry about upper and lowercase letters.
count = 0
new_vowel = []
for i in user_ask:
if i in vowel:
count += 1
new_vowel.append(i)
print("number of vowels\n", count)
you can use counter if you want to print them in a key value pairs, i.e. as a dictionary.
from collections import Counter
dict(Counter(new_vowel))
Output
enter a string to count the vowel: I am trying to learn
number of vowels :
6
and the dictionary form is:
{'i': 2, 'a': 2, 'o': 1, 'e': 1}

why my code does not decode the encrypted string based on the dictionary?

I have a dictionary with keys and values that represent letters.
for example a simple one :
DICT_CODE = {'b' : 'g', 'n' :'a', 'p' : 'o', 'x' : 'd', 't' : 'y'}
I've received an encrypted code and turned the string into a list, where each item is a word. I need to solve it, according to the items in the dictionary.
an example for a code is :
words_list = ["bppx","xnt!"] # "good day!"
I've tried to solve it by using double for loops, as here:
for word in words_list:
for char in word:
if char in string.letters:
word = word.replace(char, DICT_CODE.get(char))
print words_list
expected output -> ["good","day!"]
output -> ["bppx","xnt!"]
It does not working at all. the charcaters stay the same and the code is stil unknown.
I don't understand why it isn't working, if someone has time to look and try to help me and see whats wrong, or even suggest a better way (that works).
Changing the word variable inside the for loop, would not change the string inside the word_list. You would need to remember the index and update the element at that index (and get the word from the index) -
for i, word in enumerate(words_list):
for char in word:
if char in string.letters:
words_list[i] = words_list[i].replace(char, DICT_CODE.get(char))
Demo -
>>> words_list = ["bppx","xnt!"]
>>> DICT_CODE = {'b' : 'g', 'n' :'a', 'p' : 'o', 'x' : 'd', 't' : 'y'}
>>> for i, word in enumerate(words_list):
... for char in word:
... if char in string.letters:
... words_list[i] = words_list[i].replace(char, DICT_CODE.get(char))
>>> words_list
['good', 'day!']
But an easier way for you would be to use str.translate (along with string.maketrans ). Example -
table = string.maketrans('bnpxt','gaody') #First argument characters in your original string, and second argument what they map to.
for i, word in enumerate(words_list):
words_list[i] = word.translate(table)
Demo -
>>> import string
>>> table = string.maketrans('bnpxt','gaody') #This creates the translation table
>>> words_list = ["bppx","xnt!"]
>>> for i, word in enumerate(words_list):
... words_list[i] = word.translate(table)
...
>>> print words_list
['good', 'day!']
This using list comprehension -
words_list[:] = [word.translate(table) for word in words_list]
Demo -
>>> words_list = ["bppx","xnt!"]
>>> table = string.maketrans('bnpxt','gaody')
>>> words_list[:] = [word.translate(table) for word in words_list]
>>> words_list
['good', 'day!']
Your problem is that you don't actually modify original list.
for i, word in enumerate(words_list):
for char in word:
if char in string.letters:
word = word.replace(char, DICT_CODE.get(char))
words_list[i] = word
print words_list
['good', 'day!']
As mentioned in the comments, by #marmeladze, print word_list will print the word_list which you declared above.
What you want, is something like this:
DICT_CODE = {'b' : 'g', 'n' :'a', 'p' : 'o', 'x' : 'd', 't' : 'y', '!': '!'}
words_list = ["bppx","xnt!"]
decoded_list = []
for word in words_list:
for char in word:
word = word.replace(char, DICT_CODE.get(char))
decoded_list.append(word)
print decoded_list
Output
['good', 'day!']
Hope this helps.

Categories

Resources