How to count the letters in a word? [duplicate] - python

This question already has answers here:
Letter Count on a string
(12 answers)
Closed 5 years ago.
I am trying to make a Python script which counts the amount of letters in a randomly chosen word for my Hangman game.
I already looked around on the web, but most thing I could find was count specific letters in a word. After more looking around I ended up with this, which does not work for some reason. If someone could point out the errors, that'd be greatly appreciated.
wordList = ["Tree", "Fish", "Monkey"]
wordChosen = random.choice(wordList)
wordCounter = wordChosen.lower().count['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
print(wordCounter)

Are you looking for collections.Counter?
>>> import collections
>>> print(collections.Counter("Monkey"))
Counter({'M': 1, 'y': 1, 'k': 1, 'o': 1, 'n': 1, 'e': 1})
>>> print(collections.Counter("Tree"))
Counter({'e': 2, 'T': 1, 'r': 1})
>>> c = collections.Counter("Tree")
>>> print("The word 'Tree' has {} distinct letters".format(len(c)))
The word 'Tree' has 3 distinct letters
>>> print("The word 'Tree' has {} instances of the letter 'e'".format(c['e']))
The word 'Tree' has 2 instances of the letter 'e'

First off, your code contains an error that is rather important to understand:
wordChosen.lower().count['a', 'b'] #...
count is a function and so it requires you to surround its parameters with parentheses and not square brackets!
Next you should try to refer to Python Documentation when using a function for the first time. That should help you understand why your approach will not work.
Now to address your problem. If you want to count the number of letters in your string use len(wordChosen) which counts the total number of characters in the string.
If you want to count the frequencies of each letter a few methods have already been suggested. Here is one more using a dictionary:
import string
LetterFreq={}
for letter in string.ascii_lowercase:
LetterFreq[letter] = 0
for letter in wordChosen.lower():
LetterFreq[letter] += 1
This has the nice perk of defaulting all letters not present in the word to a frequency of 0 :)
Hope this helps!

Problem:The count method only takes in one argument and you are trying to pass a whole list.
Solution:Simply iterate over all the letters, then test if they are in the string before you print them and their amount.
import random
wordList = ["Tree", "Fish", "Monkey"]
wordChosen = random.choice(wordList)
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
for letter in letters:
if letter in wordChosen.lower():
amount = str(wordChosen.lower().count(letter))
print(letter + " : " + amount)
Result:If the random word chosen is "Tree":
e : 2
r : 1
t : 1
Conclusion:Using collections is definitely a more effective method, but I believe the way I have shown above creates more of the output you were looking for.

Related

Python ignore punctuation and white space

string = "Python, program!"
result = []
for x in string:
if x not in result:
result.append(x)
print(result)
This program makes it so if a repeat letter is used twice in a string, it'll appear only once in the list. In this case, the string "Python, program!" will appear as
['P', 'y', 't', 'h', 'o', 'n', ',', ' ', 'p', 'r', 'g', 'a', 'm', '!']
My question is, how do I make it so the program ignores punctuation such as ". , ; ? ! -", and also white spaces? So the final output would look like this instead:
['P', 'y', 't', 'h', 'o', 'n', 'p', 'r', 'g', 'a', 'm']
Just check if the string (letter) is alphanumeric using str.isalnum as an additional condition before appending the character to the list:
string = "Python, program!"
result = []
for x in string:
if x.isalnum() and x not in result:
result.append(x)
print(result)
Output:
['P', 'y', 't', 'h', 'o', 'n', 'p', 'r', 'g', 'a', 'm']
If you don't want numbers in your output, try str.isalpha() instead (returns True if the character is alphabetic).
You can filler them out using the string module. This build in library contains several constants that refer to collections of characters in order, like letters and whitespace.
import string
start = "Python, program!" #Can't name it string since that's the module's name
result = []
for x in start:
if x not in result and (x in string.ascii_letters):
result.append(x)
print(result)

Returning a set for all individual letters, vs a set for each word

I don't understand why I am receiving a set for each individual letter when I have the code below; however, when I simply remove the '''if word in 'abcdefghijklmnopqrstuvwxyz ':''' then I receive a set for each phrase. However, I need something that will remove anything that isn't a space (i.e. / [ ] - etc., from the larger passage, so the abcd was the best I could think of for this).
Two follow-up questions:
It seems that if I use return vs print, I receive two different answers (return only returns the last set; where print returns all sets).
Rather than having it be 5 individual sets, how would I put this into a list of 5 sets?
def make_itemsets(words):
words = str(words)
words.lower().split()
for word in words:
newset = set()
if word in 'abcdefghijklmnopqrstuvwxyz ':
newset.update(word)
print(newset)
words = ['sed', 'ut', 'perspiciatis', 'unde', 'omnis']
make_itemsets(words)
This returns the five lists (but doesn't remove all excess and won't remove non-characters from the larger passage):
def make_itemsets(words):
words = str(words)
words.lower().split()
for word in words:
newset = set()
newset.update(word)
print(newset)
This would be expected output:
[{'d', 'e', 's'},
{'t', 'u'},
{'a', 'c', 'e', 'i', 'p', 'r', 's', 't'},
{'d', 'e', 'n', 'u'},
{'i', 'm', 'n', 'o', 's'}]
You can have your expected output like this:
print ( [set(w) for w in words] )
Output is:
[{'d', 's', 'e'}, {'u', 't'}, {'p', 'e', 'i', 'a', 'c', 'r', 's', 't'}, {'d', 'u', 'e', 'n'}, {'m', 'i', 'o', 's', 'n'}]
Note that sets have no order.
If you want words which are alphabetic characters only, you can do this:
print ( [set(w) for w in words if w.isalpha()] )
Match all clusters containing only letters:
for word in re.compile('[a-z]+').findall('sed ut perspfkdls'):
If you want to keep create a list for aggragated results:
result = []
...
result.append({c for c in word})
...
return result
Edit: I updated my answer after reading the clarification.
def make_itemsets(words):
matcher = re.compile('[a-z]+')
words = str(words).lower()
words = matcher.findall(words)
return [{c for c in w} for w in words]
Edit 2: I already gave almost a complete implementation, so I connected the dots.

Is There an Already Made Alphabet List In Python? [duplicate]

This question already has answers here:
Alphabet range in Python
(8 answers)
Closed 7 months ago.
I need to create random word/names with random.choice(alphabet) for many of my games in repl,
but it is a pain to type it out, and make uppercase versions, consonants/vowels only, etc.
Is there a built-in or importable way to get a pre-made one in python?
The string module provides several (English-centric) values:
>>> import string
>>> string.ascii_lowercase
'abcdefghijklmnopqrstuvwxyz'
>>> string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.digits
'0123456789'
You'll have to create your own vowel/consonant lists, as well as lists for other languages.
Given how short the list of vowels is, vowels and consonants aren't too painful:
>>> vowels = set("aeiou")
>>> set(string.ascii_lowercase).difference(vowels)
{'b', 'f', 'v', 'q', 's', 'w', 'y', 'l', 'g', 'j', 'z', 'c', 'h', 'p', 'x', 'd', 'm', 'n', 't', 'k', 'r'}

Python: TypeError: unsupported operand type(s) for +: 'Random' and 'str'

I'm entering a code where a word is randomly generated. But it says TypeError and that random can't be matched with string
I've tried rewriting code multiple times but it didn't work.
Code:
import random
from random import *
Letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
LettersInWord = Random()
Points = 0
print(LettersInWord + " is number of letters in word")
for index in range(LettersInWord):
Word = Letters[Random.random(0, 25)]
Guess = input("Enter Word You Think It Is (You will get a point everytime
one or more of your letters match with the word. Your turn will end when
you enter a letter that is not in the word: ")
for letter in Guess:
if letter == letter in Word:
Points = Points + 1
if Guess == Word:
print("Congratulations, you won. End program and restart to
try again.")
Guess = input("Well done, try again")
Random() is a random-number generator, not a number itself.
letters_in_word = randint(1,25) # random number between 1 and 25, inclusive
(Capitalized names are conventionally reserved for class names. Use snake case identifiers for ordinary variables.)
Continuing from the comments:
from random import *
Letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
while True:
letters_in_word = randint(1,25)
Points = 0
Word = []
print("{} is number of letters in word".format(letters_in_word))
for index in range(0, letters_in_word):
Word.append(Letters[randint(0, 25)])
Guess = input("Press Q/q to exit or Enter Word You Think It Is (You will get a point everytime one or more of your letters match with the word. Your turn will end when you enter a letter that is not in the word: ")
if Guess.lower() == 'q':
break
print(Word)
if Guess in Word:
Points = 100 # assuming
print("Congratulations, you won. End program and restart to try again.\nTotal Points: {}".format(Points))
break
else:
for letter in Guess:
if letter in Word:
Points = Points + 1
print("Total Points: {}".format(Points))
OUTPUT:
10 is number of letters in word
Press Q/q to exit or Enter Word You Think It Is (You will get a point everytime one or more of your letters match with the word. Your turn will end when you enter a letter that is not in the word: pak
['f', 't', 'l', 'b', 'd', 'k', 'e', 'p', 'd', 'n']
Total Points: 2
9 is number of letters in word
Press Q/q to exit or Enter Word You Think It Is (You will get a point everytime one or more of your letters match with the word. Your turn will end when you enter a letter that is not in the word: dirt
['z', 'i', 'k', 'p', 'z', 'j', 'r', 't', 'd']
Congratulations, you won. End program and restart to try again.
Total Points: 100
Process finished with exit code 0

Python Itertools Code Optimisation

Given question (the contest is now over)
a password consists of exactly n lowercase English letters.
the password is melodious, meaning that consonants can only be next to
vowels and vowels can only be next to consonants. Example: bawahaha
the password cannot contain the letter y (because it's both a
consonant and vowel).
the first letter of the password can be either
a vowel or consonant.
Given the length, n, of the password,
print all of the possible passwords that meet the conditions above.
Input Format
The line of input contains the integer (the length of the password).
Constraints
Output Format
Print each of the possible passwords, one per line. The order of the passwords does not matter.
My Code in Python:
import sys
import itertools
n = int(raw_input().strip())
consonants = ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'z']
vowels = ['a', 'e', 'i', 'o', 'u']
test4 = ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'z', 'a', 'e', 'i', 'o', 'u']
answer = set(itertools.product(test4, repeat=n))
for letters in answer:
for j in xrange(len(letters)):
flag = 1
if j != len(letters) - 1:
if letters[j] in vowels and letters[j+1] in vowels:
flag = 0
break
if letters[j] in consonants and letters[j+1] in consonants:
flag = 0
break
if flag:
for j in letters:
sys.stdout.write(j)
print ""
Is there a better way to do this?
Of course there's a better way (if you mean faster). You can generate a itertools.product where you don't have to "discard" items.
You can simply create a product of vowel, consonant, vowel, consonant, ... (alternating both lists n times) and one which starts with consonant, vowel, consonant, vowel, .... The returned items will always satisfy the condition so all that needs to be done is printing them.
import itertools
def alternating(seq1, seq2, length):
"""Generator that alternatingly yields seq1 and seq2, `length` times"""
assert length >= 0
for _ in range(length // 2):
yield seq1
yield seq2
if length % 2 == 1:
yield seq1
consonants = ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'z']
vowels = ['a', 'e', 'i', 'o', 'u']
n = int(raw_input().strip())
# Starts with vowel
for comb in itertools.product(*list(alternating(vowels, consonants, n))):
print(''.join(comb))
# Starts with consonant
for comb in itertools.product(*list(alternating(consonants, vowels, n))):
print(''.join(comb))
That way you can reduce the number of possible candidates.
Your approach gave 25**n items, while the new approach only generates 2 * 5**(n//2)*20**(n//2) (if n even) or 5**(n//2 + 1) * 20 ** (n//2) + 5**(n//2) * 20 ** (n//2 + 1) (if n odd) items.
For n=5 that means: What generated originally 9765625 items (almost 10 million!) from product will now only generate 250000 items. Even ignoring the (possibly very expensive) check if your sequence satisfies the problem-condition (which is obsolete now) you generated 40 times more items in your product!

Categories

Resources