The code I have below is supposed to run the number of words that start with a certain letter, but when I run it, the counts are all 0, instead of what they should be: {'I': 2, 'b': 2, 't': 3, 'f': 1}. I appreciate any help. Thanks!
def initialLets(keyStr):
'''Return a dictionary in which each key is the initial letter of a word in t and the value is the number of words that begin with that letter. Upper
and lower case letters should be considered different letters.'''
inLets = {}
strList = keyStr.split()
firstLets = []
for words in strList:
if words[0] not in firstLets:
firstLets.append(words[0])
for lets in firstLets:
inLets[lets] = strList.count(lets)
return inLets
text = "I'm born to trouble I'm born to fate"
print(initialLets(text))
You can try this:
text = "I'm born to trouble I'm born to fate"
new_text = text.split()
final_counts = {i[0]:sum(b.startswith(i[0]) for b in new_text) for i in new_text}
Output:
{'I': 2, 'b': 2, 't': 3, 'f': 1}
You don't have a counter as you append the letter but not its number of occurrences.
So to simplify:
def initialLets(keyStr):
'''Return a dictionary in which each key is the initial letter of a word in t and the value is the number of words that begin with that letter. Upper
and lower case letters should be considered different letters.'''
strList = keyStr.split()
# We initiate the variable that gonna take our results
result = {}
for words in strList:
if words[0] not in result:
# if first letter not in result then we add it to result with counter = 1
result[words[0]] = 1
else:
# We increase the number of occurence
result[words[0]] += 1
return result
text = "I'm born to trouble I'm born to fate"
print(initialLets(text))
Firstly, you are checking if the first letter of the word is in the list before putting it in. That would just make the list comprise of only 1 of each letter. Secondly, your strList is a list of each word, instead of inLets[lets] = strList.count(lets), it should be inLets[lets] = firstLets.count(lets)... While your current code isn't the cleanest way to do it, this minor modification would have worked.
def initialLets(keyStr):
'''Return a dictionary in which each key is the initial letter of a word in t and the value is the number of words that begin with that letter. Upper
and lower case letters should be considered different letters.'''
inLets = {}
strList = keyStr.split()
firstLets = []
for words in strList:
firstLets.append(words[0])
for lets in firstLets:
inLets[lets] = firstLets.count(lets)
return inLets
text = "I'm born to trouble I'm born to fate"
print(initialLets(text))
Related
I need to return a dictionary that counts the number of times each letter in a predetermined list occurs. The problem is that I need to count both Upper and Lower case letters as the same, so I can't use .lower or .upper.
So, for example, "This is a Python string" should return {'t':3} if "t" is the letter being searched for.
Here is what I have so far...
def countLetters(fullText, letters):
countDict = {i:0 for i in letters}
lowerString = fullText.lower()
for i in lowerString:
if i in letters:
countDict[i] += 1
return countDict
Where 'letters' is the condition and fullText is the string I am searching.
The obvious issue here is that if the test is "T" rather than "t", my code won't return anything Sorry for any errors in my terminology, I am pretty new to this. Any help would be much appreciated!
To ignore capitalization, you need to input =
input = input.lower ()
.Lists all characters of the input text using list operations.
It can also be used as a word counter if you scan the space character.
input = "Batuq batuq BatuQ" # Reads all inputs up to the EOF character
input = input.replace('-',' ')#Replace (-, + .etc) expressions with a space character.
input = input.replace('.','')
input = input.replace(',','')
input = input.replace("`",'')
input = input.replace("'",'')
#input= input.split(' ') #if you use it, it will sort by the most repetitive words
dictionary = dict()
count = 0
for word in input:
dictionary[word] = input.count(word)
print(dictionary)
#Writes the 5 most repetitive characters
for k in sorted(dictionary,key=dictionary.get,reverse=True)[:5]:
print(k,dictionary[k])
Would something like this work that handles both case sensitive letter counts and non case sensitive counts?
from typing import List
def count_letters(
input_str: str,
letters: List[str],
count_case_sensitive: bool=True
):
"""
count_letters consumes a list of letters and an input string
and returns a dictionary of counts by letter.
"""
if count_case_sensitive is False:
input_str = input_str.lower()
letters = list(set(map(lambda x: x.lower(), letters)))
# dict comprehension - build your dict in one line
# Tutorial on dict comprehensions: https://www.datacamp.com/community/tutorials/python-dictionary-comprehension
counts = {letter: input_str.count(letter) for letter in letters}
return counts
# define function inputs
letters = ['t', 'a', 'z', 'T']
string = 'this is an example with sTrings and zebras and Zoos'
# case sensitive
count_letters(
string,
letters,
count_case_sensitive=True
)
# {'t': 2, 'a': 5, 'z': 1, 'T': 1}
# not case sensitive
count_letters(
string,
letters,
count_case_sensitive=False
)
# {'a': 5, 'z': 2, 't': 3} # notice input T is now just t in dictionary of counts
Try it - like this:
def count_letters(fullText, letters):
countDict = {i: 0 for i in letters}
lowerString = fullText.lower()
for i in lowerString:
if i in letters:
countDict[i] += 1
return countDict
test = "This is a Python string."
print(count_letters(test, 't')) #Output: 3
You're looping over the wrong string. You need to loop over lowerString, not fullString, so you ignore the case when counting.
It's also more efficient to do if i in countDict than if i in letter.
def countLetters(fullText, letters):
countDict = {i.lower():0 for i in letters}
lowerString = fullText.lower()
for i in lowerString:
if i in countDict:
countDict[i] += 1
return countDict
What you can do is simply duplicate the dict with both upper and lowercase like so:
def countLetters(fullText, letters):
countDict = {}
for i in letters:
countDict[i.upper()]=0
countDict[i.lower()]=0
lowerString = fullText.lower()
letters = letters.lower()
for i in lowerString:
if i in letters:
countDict[i] += 1
if (i!=i.upper()):
countDict[i.upper()] +=1
return countDict
print(countLetters("This is a Python string", "TxZY"))
Now some things you can also do is loop over the original string and change countDict[i] += 1 to countDict[i.lower()] +=1
Use the Counter from the collections module
from collections import Counter
input = "Batuq batuq BatuQ"
bow=input.split(' ')
results=Counter(bow)
print(results)
output:
Counter({'Batuq': 1, 'batuq': 1, 'BatuQ': 1})
I'm new to coding. I tried to build a simple code that can take a subset of alphabet letters and return back a valid words from a text based dictionary.
In the code below, I ask the user to input a number of characters (e.g. abcdef) then the program will make words out of these letters.
Now my question is this the best method to do it in term of performance, code length and the blocks sequence? If not, can you suggest a better way to do?
#Read the dictionary
fh = open('C:\\english-dict2.txt')
dict = []
while True:
line = fh.readline()
dict.append(line.strip())
if not line:
break
fh.close()
#Input letters
letters = input("Please enter your letters: ")
letters_list=[]
for l in letters:
letters_list.append(l)
mini = 2 #default value
maks = len(letters_list)
mini = input("Minimum length of the word (default is 2): ")
if mini == "":
mini = 2 #default value
mini = int(mini)
#Here I create a new dictionary based on the number of letters input or less than.
newdic=[]
for words1 in dict:
if len(words1) <= maks and len(words1)>= mini:
newdic.append(words1)
for words2 in newdic:
ok = 1
for i in words2:
if i in letters_list:
ok = ok * 1
else:
ok = ok * 0
if ok == 1:
print(words2)
Lists are inefficient for lookups. You should use a dict of sets instead to index every word with each letter in the word, so that you can simply use set intersection to find the words that contain all of the given letters:
from functools import reduce
d = {}
with open('C:\\english-dict2.txt') as f:
for l in f:
w = l.strip()
for c in set(w):
d.setdefault(c, set()).add(w)
letters = input("Please enter your letters: ")
print(reduce(lambda a, b: a & d[b], letters[1:], d[letters[0]]))
For example, given a dictionary of the following words:
apple
book
cat
dog
elephant
The index dictionary d would become:
{'p': {'elephant', 'apple'}, 'a': {'cat', 'elephant', 'apple'}, 'l': {'elephant', 'apple'}, 'e': {'elephant', 'apple'}, 'k': {'book'}, 'b': {'book'}, 'o': {'book', 'dog'}, 'c': {'cat'}, 't': {'cat', 'elephant'}, 'd': {'dog'}, 'g': {'dog'}, 'h': {'elephant'}, 'n': {'elephant'}}
Here's a sample input/output of the above code, where both the words apple and elephant are found to contain both of the letters a and e:
Please enter your letters: ae
{'apple', 'elephant'}
From here you can easily filter the resulting set based on a given minimum number of letters if you want.
modification 1: You do not need to loop over letters in letters, just
letters_list=list(letters)
is enough to make list of letters.
modification2: You can make sure any mini can be handled using:
try:
mini = int(mini)
except:
mini = 2
For your dictionary, you don't need to iterate through using readline(), just do:
with open(path) as fh:
dict = readlines()
This will also safely close your file, even if there's an error. If you want to do lookups for words, I'd use a set rather than a list, as the lookups in sets are O(1), whereas lookups in list are not, they are O(n).
d_set = set(dict)
This way if you want to create all combinations of letters, you can look them up like so:
import itertools
letters = input("Input your letters, please ")
def check_for_match(combos):
for combo in combos:
if combo in d_set:
yield combo
i = len(letters)
my_list = []
while i:
combos = itertools.permutations(words, i)
results = list(check_for_match(combos))
my_list = [*my_list, *results]
i-=1
This will give you all of the permutations of letters, check if they are in your dictionary, and build my_list if they are. I think that's what you are looking for
In the code below Question 13a asks me to have the function count how many vowels are in a string. (I don't have to call that function in my homework.) But I called it to test it out and that part is completely correct and it works. The string can be both uppercase and lowercase with NO punctuation.
Question 13b asks to create a dictionary. The key is the word in a string (the string has multiple words). The value is how many vowels in that individual word. The question is asking this: If the word has AT LEAST i amount of vowels, then append it to the dictionary (The word with the amount vowels) This function has two parameters. The first one is a string with NO punctuation. The second parameter represents the number of how many vowels the word MUST have to be appended to the dictionary. The professor wants me to call Function 13a this function as part of the algorithm. That being said, the output of Question 13a is the value of the key (the individual word) in this problem. I am having trouble with this question, because I just can't get Python to append the output of 13a (the number of vowels for a word) to the dictionary key.
And also in the code below, I did not work on the part yet where I was supposed use the variable i.
Here is my code:
print("Question 13a")
def vowelCount(s):
vowels = 'aeiou'
countVowels = 0
for letter in s.lower():
if letter in vowels:
countVowels += 1
print(countVowels)
print("Question 13b")
def manyVowels(t, i):
my_string = t.split()
my_dict = {}
for word in my_string:
number = vowelCount(word)
my_dict[word].append(number)
print(my_dict)
print(manyVowels('they are endowed by their creator with certain unalienable rights', 2))
If you cannot understand the question then here is the professor's directions:
Question 13a (10 points)
The letters a, e, i, o and u are vowels. No other letter is a vowel.
Write a function named vowelCount() that takes a string, s, as a parameter and returns the
number of vowels that s contains. The string s may contain both upper and lower case characters.
For example, the function call vowelCount('Amendment') should return the integer 3 because
there are 3 occurrences of the letters 'A' and 'e'.
Question 13b (10 points)
Write a function named manyVowels() that takes a body of text, t, and an integer, i, as
parameters. The text t contains only lower case letters and white space.
manyVowels() should return a dictionary in which the keys are all words in t that contain at least i
vowels. The value corresponding to each key is the number of vowels in it. For full credit,
manyVowels() must call the helper function vowelCount() from Question 11a to determine the
number of vowels in each word. For example, if the input text contains the word "hello", then
"hello" should be a key in the dictionary and its value should be 2 because there are 2 vowels in
"hello".
Input:
1. t, a text consisting of lower case letters and white space
2. i, a threshold number of vowels
Return: a dictionary of key-value pairs in which the keys are the words in t containing at least i
vowels and the value of each key is the number of vowels it contains.
For example, the following would be correct output.
text = 'they are endowed by their creator with certain unalienable rights'
print(manyVowels(text, 3))
{'certain': 3, 'unalienable': 6, 'creator': 3, 'endowed': 3}
Add a condition to add only words with enough vovels
def vowelCount(s):
vowels = 'aeiou'
countVowels = 0
for letter in s.lower():
if letter in vowels:
countVowels += 1
return countVowels
def manyVowels(t, i):
my_string = t.split()
my_dict = {}
for word in my_string:
number = vowelCount(word)
if number >= i:
my_dict[word] = number
return my_dict
The line my_dict[word] = number adds the resuld of vowelCount(word) to your dictionary. But only if the number of vovels is at least i.
def vowelCount(s):
num_vowels=0
for char in s:
if char in "aeiouAEIOU":
num_vowels = num_vowels+1
return num_vowels
def manyVowels(text, i):
words_with_many_vowels = dict()
text_array = text.split()
for word in text_array:
if vowelCount(word) >= i:
words_with_many_vowels[word] = vowelCount(word)
return words_with_many_vowels
print(vowelCount('Amendment'))
text = 'they are endowed by their creator with certain unalienable rights'
print(manyVowels(text, 3))
Output:
3
{'creator': 3, 'certain': 3, 'endowed': 3, 'unalienable': 6}
Try it here!
Your code needs some adjustments:
The first function should return a value not print it:
return (countVowels)
The second function is not adding the key with accompanying value to the dictionary correctly. You should use:
my_dict[word] = number
return {k:v for k, v in my_dict.items() if v > i}
So, here is what I got:
def getSentence():
sentence = input("What is your sentence? ").upper()
if sentence == "":
print("You haven't entered a sentence. Please re-enter a sentence.")
getSentence()
elif sentence.isdigit():
print("You have entered numbers. Please re-enter a sentence.")
getSentence()
else:
import string
for c in string.punctuation:
sentence = sentence.replace(c,"")
return sentence
def list(sentence):
words = []
for word in sentence.split():
if not word in words:
words.append(word)
print(words)
def replace(words,sentence):
position = []
for word in sentence:
if word == words[word]:
position.append(i+1)
print(position)
sentence = getSentence()
list = list(sentence)
replace = replace(words,sentence)
I have only managed to get this far, my full intention is to take the sentence, seperate into words, change each word into a number e.g.
words = ["Hello","world","world","said","hello"]
And make it so that each word has a number:
So lets say that "hello" has the value of 1, the sentence would be '1 world world said 1'
And if world was 2, it would be '1 2 2 said 1'
Finally, if "said" was 3, it would be '1 2 2 1 2'
Any help would be greatly appreciated, I will then develop this code so that the sentence and such is stored into a file using file.write() and file.read() etc
Thanks
If you want just the position in which each word is you can do
positions = map(words.index,words)
Also, NEVER use built-in function names for your variables or functions. And also never call your variables the same as your functions (replace = replace(...)), functions are objects
Edit: In python 3 you must convert the iterator that map returns to a list
positions = list(map(words.index, words))
Or use a comprehension list
positions = [words.index(w) for w in words]
Does it matter what order the words are turned into numbers? Is Hello and hello two words or one? Why not something like:
import string
sentence = input() # user input here
sentence.translate(str.maketrans('', '', string.punctuation))
# strip out punctuation
replacements = {ch: str(idx) for idx, ch in enumerate(set(sentence.split()))}
# builds {"hello": 0, "world": 1, "said": 2} or etc
result = ' '.join(replacements.get(word, word) for word in sentence.split())
# join back with the replacements
Another idea (although don't think it's better than the rest), use dictionaries:
dictionary = dict()
for word in words:
if word not in dictionary:
dictionary[word] = len(dictionary)+1
Also, on your code, when you're calling "getSentence" inside "getSentence", you should return its return value:
if sentence == "":
print("You haven't entered a sentence. Please re-enter a sentence.")
return getSentence()
elif sentence.isdigit():
print("You have entered numbers. Please re-enter a sentence.")
return getSentence()
else:
...
Recently I have been working on a word game in python, nonetheless I am having problems with a little detail.The idea of the game is to create words with letters in a hand given randomly. The function that coordinates the game asks the user to input a letter and according to it, lets him/her to play a new hand, play the same hand again or exit the game. The problem is that I cannot make the game to return to the previous hand and let the user play it again. Instead the code returns a modified version of the previous hand, so that if you inputted a word correctly the letters in that word won't be in it. I thought this could not be possible since the function that "updates the hand" lies on a different scope. I am working in python 3.2.1
I posted the entire code so you could test it and see what it does. The problem, however, lies in the functions: play_game, play_hand and update_hand.
import random
import string
VOWELS = 'aeiou'
CONSONANTS = 'bcdfghjklmnpqrstvwxyz'
HAND_SIZE = 7
SCRABBLE_LETTER_VALUES = {
'a': 1, 'b': 3, 'c': 3, 'd': 2, 'e': 1, 'f': 4, 'g': 2, 'h': 4, 'i': 1, 'j': 8, 'k': 5, 'l': 1, 'm': 3, 'n': 1, 'o': 1, 'p': 3, 'q': 10, 'r': 1, 's': 1, 't': 1, 'u': 1, 'v': 4, 'w': 4, 'x': 8, 'y': 4, 'z': 10
}
WORDLIST_FILENAME = "words.txt"
def load_words():
"""
Returns a list of valid words. Words are strings of lowercase letters.
Depending on the size of the word list, this function may
take a while to finish.
"""
print ("Loading word list from file...")
# inFile: file
inFile = open(WORDLIST_FILENAME, 'r')
# wordlist: list of strings
wordlist = []
for line in inFile:
wordlist.append(line.strip().lower())
print (" ", len(wordlist), "words loaded.")
return wordlist
def get_frequency_dict(sequence):
"""
Returns a dictionary where the keys are elements of the sequence
and the values are integer counts, for the number of times that
an element is repeated in the sequence.
sequence: string or list
return: dictionary
"""
# freqs: dictionary (element_type -> int)
freq = {}
for x in sequence:
freq[x] = freq.get(x,0) + 1
return freq
def get_word_score(word, n):
"""
Returns the score for a word. Assumes the word is a
valid word.
The score for a word is the sum of the points for letters
in the word multiplied by the length of the word, plus 50
points if all n letters are used on the first go.
Letters are scored as in Scrabble; A is worth 1, B is
worth 3, C is worth 3, D is worth 2, E is worth 1, and so on.
word: string (lowercase letters)
returns: int >= 0
"""
score = 0
for character in word:
score = score + (SCRABBLE_LETTER_VALUES[character])
score = score * len(word)
if len(word) == 7:
score = score + 50
return score
def display_hand(hand):
"""
Displays the letters currently in the hand.
For example:
display_hand({'a':1, 'x':2, 'l':3, 'e':1})
Should print out something like:
a x x l l l e
The order of the letters is unimportant.
hand: dictionary (string -> int)
"""
for letter in hand.keys():
for j in range(hand[letter]):
print (letter,)
def deal_hand(n):
"""
Returns a random hand containing n lowercase letters.
At least n/3 the letters in the hand should be VOWELS.
Hands are represented as dictionaries. The keys are
letters and the values are the number of times the
particular letter is repeated in that hand.
n: int >= 0
returns: dictionary (string -> int)
"""
hand={}
num_vowels = int(n / 3)
for i in range(num_vowels):
x = VOWELS[random.randrange(0,len(VOWELS))]
hand[x] = hand.get(x, 0) + 1
for i in range(num_vowels, n):
x = CONSONANTS[random.randrange(0,len(CONSONANTS))]
hand[x] = hand.get(x, 0) + 1
return hand
def update_hand(hand, word):
"""
Assumes that 'hand' has all the letters in word.
In other words, this assumes that however many times
a letter appears in 'word', 'hand' has at least as
many of that letter in it.
Updates the hand: uses up the letters in the given word
and returns the new hand, without those letters in it.
Has no side effects: does not modify hand.
word: string
hand: dictionary (string -> int)
returns: dictionary (string -> int)
"""
for i in word:
new_hand = hand
new_VOWELS = VOWELS
new_CONSONANTS = CONSONANTS
if i in VOWELS:
new_VOWELS = new_VOWELS.replace("i", "")
new_hand[i] = new_hand.get(i, 0) - 1
if new_hand[i] <= 0:
new_hand.pop(i, None)
else:
new_CONSONANTS = new_CONSONANTS.replace("i", "")
new_hand[i] = new_hand.get(i, 0) - 1
if new_hand[i] <= 0:
new_hand.pop(i, None)
return (new_hand)
def is_valid_word(word, hand, word_list):
"""
Returns True if word is in the word_list and is entirely
composed of letters in the hand. Otherwise, returns False.
Does not mutate hand or word_list.
word: string
hand: dictionary (string -> int)
word_list: list of lowercase strings
"""
for character in word:
x = 0
if character in hand:
x = x + 1
if (x==(len(word)-1)) and (word in word_list):
return (True)
else:
return (False)
def calculate_handlen(hand):
handlen = 0
for v in hand.values():
handlen += v
return handlen
def play_hand(hand, word_list):
"""
Allows the user to play the given hand, as follows:
* The hand is displayed.
* The user may input a word.
* An invalid word is rejected, and a message is displayed asking
the user to choose another word.
* When a valid word is entered, it uses up letters from the hand.
* After every valid word: the score for that word is displayed,
the remaining letters in the hand are displayed, and the user
is asked to input another word.
* The sum of the word scores is displayed when the hand finishes.
* The hand finishes when there are no more unused letters.
The user can also finish playing the hand by inputing a single
period (the string '.') instead of a word.
hand: dictionary (string -> int)
word_list: list of lowercase strings
"""
score = 0
han = hand
while True:
print ("Score= ", score)
word = str(input("Enter your word: "))
value = is_valid_word(word, han, word_list)
if value == True:
print ("Congratulations, that word is worth", get_word_score(word, 7), "points")
print ("Please input another word")
han = update_hand(han, word)
print ("Current hand=")
display_hand(han)
score = score + get_word_score(word, 7)
elif word == "." or len(hand)==0:
break
else:
print ("Current hand=")
display_hand(han)
print ("Sorry, that word is not valid")
print ("Please choose another word")
def play_game(word_list):
"""
Allow the user to play an arbitrary number of hands.
* Asks the user to input 'n' or 'r' or 'e'.
* If the user inputs 'n', let the user play a new (random) hand.
When done playing the hand, ask the 'n' or 'e' question again.
* If the user inputs 'r', let the user play the last hand again.
* If the user inputs 'e', exit the game.
* If the user inputs anything else, ask them again.
"""
global handy
handy = deal_hand(7)
while True:
print ("Use 'n' to play a new hand, 'r' to play the last hand again or 'e' to exit game")
inp = str(input("Enter a letter:'n' or 'r' or 'e': ="))
if inp == 'n':
hand = deal_hand(7)
handy = hand
print("Current hand =")
display_hand(hand)
play_hand(hand, word_list)
elif inp == 'r':
print("Current hand =")
display_hand(handy)
play_hand(handy, word_list)
elif inp == 'e':
exit(play_game)
else:
print ("Please input a valid letter")
if __name__ == '__main__':
word_list = load_words()
play_game(word_list)
Writing y = x makes y refer to the same thing as x. It does NOT copy x. With "immutable" objects, this looks like a copy because you have to make a new object in order for any "change" to be evident. With "mutable" objects like lists, because x and y both refer to the same object, changes to one name appear in the other.
You probably want to copy the list:
new_hand = hand[:] # this funny slicing notation produces a shallow copy of the original list