I'm currently learning python and I'm struggling in a problem which I need to get a name as input from a user and get the first letter of the name and depending on the letter, tell him what day of the week he needs to go (context doesn't matter), so:
Monday: A - C; Tuesday: D - G; Wednesday: H - L; Thursday: M; Friday: N - Q; Saturday: R - S; Sunday: T - Z.
tuple_letter = (['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'])
tuple_week = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
name = input("Name: \n")
for letters in tuple_letter:
if letters.count(name[0]) >= 1:
print(name + ", you should go to the hospital on " + tuple_week[letters])
I thought that just like in c# for example, "letters" inside the for, it'd actually act like the i++, that it counts as a number but in fact, python itself knows that when we say "for letters in tuple_letter" I'm actually refering to the lists inside the list "tuple_letter", so it does not work since I was basing my logic on the fact that I'd use it to refer to the element of each list, because i put each element of each list in the same order (Monday and 'a','b','c' == 1, ....)
To conclude and connect with the title, I had an idea where I'd create a dictionary where each key would be the respective day of the week for a list of letters, just like I tried.
So, how can I do this? Is it possible? Better ways?
You can, it might make a bit more logical sense. Working with dictionaries can be easy in Python since they follow the standards of JSON. Obligatory reading here: https://www.w3schools.com/python/python_dictionaries.asp
Your example would involve a dictionary like this:
example_dict = {
"Monday": ['a', 'b', 'c'],
"Tuesday": ['d', 'e', 'f', 'g'],
"Wednesday": ['h', 'i', 'j', 'k', 'l'],
"Thursday": ['m'],
"Friday": ['n', 'o', 'p', 'q'],
"Saturday": ['r', 's', 't'],
"Sunday": ['u', 'v', 'w', 'x', 'y', 'z']
}
From there you can iterate using a for loop and follow the index lookup with something like example_dict[x]. Here's the second part of your code refactored to show this:
name = input("Name: \n")
if len(name) > 0:
for i in example_dict:
# Lower case the letter for comparison
if name[0].lower() in example_dict[i]:
print(name + ", you should go to the hospital on " + i)
You can store lists in dictionaries! So once you've iterated the values it's just a matter of checking what day contains the letter of the name you're analyzing.
I hope this helps you get started.
Dictionaries work by having keys corresponding to values, so if you do dict[key] or dict.get(key), you get the value.
The issue is that, with your scenario, it gets a little repetitive coding it.
letter_to_day = {
'a':"Monday",
'b':"Monday",
'c':"Monday",
'd':"Tuesday",
... # fair amount of typing
'z':"Sunday"
}
name = input("Name: \n")
print(name + ", you should go to the hospital on " + letter_to_day[name[0].lower()])
#raises an error if it isn't a letter
print(name + ", you should go to the hospital on " + letter_to_day.get(name[0].lower(), "not a letter"))
#this one will return "not a letter" if it isn't found
You can do some workarounds, like doing
letter_to_day = {}
for day in tuple_week:
for letters in tuple_letter:
for letter in letters:
letter_to_day[letter] = day
instead of typing it all out, or even doing print(letter_to_day) and copy-and-pasting the result.
But it turns out that there is another way - you can use inequalities with strings(and also lists, but that's not important).
Strings later alphabetically are greater, while strings earlier are lesser. "a" < "b" is True.
So that means you can do something like
def letter_to_day(letter):
if "a" <= letter <= "c":
return "Monday"
elif "d" <= letter <= "g":
return "Tuesday"
elif "h" <= letter <= "l":
return "Wednesday"
elif letter == "m":
return "Thursday"
elif "n" <= letter <= "q":
return "Friday"
elif "r" <= letter <= "s":
return "Saturday"
elif "t" <= letter <= "z":
return "Sunday"
else:
return "not a letter"
name = input("Name: \n")
print(name + ", you should go to the hospital on " + letter_to_day(name[0].lower()))
The answer on this post by iamwbj answers your question about having a dictionary that has days as its keys and lists of letters as its values. I think mine is faster, although it doesn't go in the direction you were expecting.
P.S. I wasn't sure if you actually meant Saturday R-S; Sunday: T-Z - your example code and question conflicted.
tuple_letter = (['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'])
tuple_week = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
dictionary = dict(zip(tuple_week, tuple_letter))
print(dictionary)
name = input("Name: \n")
for key, value in dictionary.items():
if name.lower()[0] in value:
print(name.capitalize() , ", you should go to the hospital on " , key)
Make Dict using inbuilt function and also more attention towards key and value pair
You can input either in Upper case or lower case because during comparison it makes lower case then compare
There two points you are missing:
the list index must be an integer
add the initial parameter like i to represent the index
use break to exit the for loop while check over
the name should be changed to lower case
add lower() to convert name[0]
tuple_letter = (['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'])
tuple_week = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
name = input("Name: \n")
i = 0
for letters in tuple_letter:
if letters.count(name[0].lower()) >= 1:
print(name + ", you should go to the hospital on " + tuple_week[i])
break
i += 1
Related
note: the letters are there twice so when shifting a letter at the end of the alphabet i dont get a out of range error
so currently im working on a caesers cypher where you write a word and shift those letters by a certain amount of times
input = abc
output = bcd
my issue is when the code runs it prints the output letters twice
input = abc
output = bbccdd
heres my code
alphabet = ['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', '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']
direction = input("Type 'encode' to encrypt, type 'decode' to decrypt:\n")
text = input("Type your message:\n").lower()
shift = int(input("Type the shift number:\n"))
def encrypt(text, shift):
cipher_text = ""
for i in text:
for letter in alphabet:
if i == letter:
index = alphabet.index(letter)
shifted_index = index + shift
shifted_letter = alphabet[shifted_index]
cipher_text += shifted_letter
print(f"The encoded word is {cipher_text}")
encrypt(text, shift)
another example
input = zulu
expected output = avmv
code output = aavvmmvv
Lots of work for what is essentially a one-liner:
import string
alphabet = string.ascii_lowercase # use the predefined string of lower case letters from the string module
index = {ch: i for i, ch in enumerate(alphabet)} # pre-calculate the index of each character once.
def encrypt(txt, n):
return ''.join(alphabet[(index[c] + n) % len(alphabet)] for c in txt)
print(encrypt('spin', 5))
prints
xuns
the modulo operation (ie. ... % len(alphabet)) makes sure the index is within bounds of the alphabet after adding the shift - no matter how big the shift is.
leave it at "for i in text" their is no need for "for letter in alphabet" that is why it is looping through. If that doesnt work take out the duplicates in your alphabet. I didnt notice that on first glance.
Remove the inner for loop and the if and then find the first index of the current character in the alphabet.
def encrypt(text, shift):
cipher_text = ""
for i in text:
index = alphabet.index(i)
shifted_index = index + shift
shifted_letter = alphabet[shifted_index]
cipher_text += shifted_letter
print(f"The encoded word is {cipher_text}")
This code sticks closely to your approach. There are better solutions, like the one from #thebjorn.
As mentioned above, you have the same alphabet twice. So, you need to exit the inner for loop once you have shifted. So, add a break after cipher_text += shifted_letter, that will exit the inner for loop.
Updated Code
alphabet = ['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', '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']
direction = input("Type 'encode' to encrypt, type 'decode' to decrypt:\n")
text = input("Type your message:\n").lower()
#shift = int(input("Type the shift number:\n"))
def encrypt(text, shift):
cipher_text = ""
for i in text:
for letter in alphabet:
if i == letter:
index = alphabet.index(letter)
shifted_index = index + shift
shifted_letter = alphabet[shifted_index]
cipher_text += shifted_letter
break # NEW LINE
print(f"The encoded word is {cipher_text}")
shift = int(input("Type the shift number:\n"))
if shift > 26:
print("Shift should be max 26, exiting...")
else:
encrypt(text, shift)
Output
Type 'encode' to encrypt, type 'decode' to decrypt:
encode
Type your message:
spin
Type the shift number:
5
The encoded word is xuns
Updated based on feedback
import string
direction = input("Type 'encode' to encrypt, type 'decode' to decrypt:\n")
text = input("Type your message:\n").lower()
shift = int(input("Type the shift number:\n"))
alphabet = string.ascii_lowercase # use the predefined string of lower case letters from the string module
index = {ch: i for i, ch in enumerate(alphabet)} # pre-calculate the index of each character once.
def encrypt(txt, n):
return ''.join(alphabet[(index[c] + n) % len(alphabet)] for c in txt)
encrypt(text, shift)
Output
Type 'encode' to encrypt, type 'decode' to decrypt:
encode
Type your message:
xylophone
Type the shift number:
100
'tuhkldkja'
I am working on a scratch lottery command on my python game.
My Scratch lottery function is below.
def lottery(player_money):
print('scratch lottery :')
print('price: 500')
print('wins :')
print(' all 6 same : $100000')
print(' all 5 same : $50000')
print(' all 4 same : $10000')
print(' all 3 same : $1000')
print(' all 2 same : $300')
print('do you want to buy it?? yes/no')
buy = input('> ')
if buy == 'no':
print('please come back later!!')
return player_money
elif buy == 'yes':
print('_____________')
lottery_results = ['x', 'o', 'p', 'k', 'm', 'e', 'a', 'w']
a = random.choice(lottery_results)
b = random.choice(lottery_results)
c = random.choice(lottery_results)
d = random.choice(lottery_results)
e = random.choice(lottery_results)
f = random.choice(lottery_results)
print('| ' + a + ' | ' + b + ' | ' + c + ' |')
print('|_' + d + '_|_' + e + '_|_' + f + '_|')
if...
I Have no idea what to put after
if...
I don't want to make if for all possible solutions since that would be like 2 million ifs.
I want to make it like below
If 2 of the str in a or b or c or d or e or f is the same:
print('Since 2 matched, you won $300!')
player_money += 300
return player_money
I don't know how to code(ify) the phrase that goes after if and the phrase that goes after if that I put in wouldn't work and there would be a error
Any suggestions on how I could make this work?
You're off to a good start, but there is something that could make your life a lot easier. Firstly, lets use random.choices to create a list from the possible letters:
import random
pool = ['x', 'o', 'p', 'k', 'm', 'e', 'a', 'w']
results = random.choices(pool, k=len(pool))
Note: k can be any integer - it determines the length of the resulting list
This is going to yield a list with random letters from the pool:
['e', 'x', 'a', 'm', 'x', 'k', 'o', 'p']
Now, you can think about how you can build your if statement off of a list.
If 2 of the str in a or b or c or d or e or f is the same:
This sounds like a job for iteration. Remember, we don't have the variables a, b, c, etc. anymore; rather, they're stored in a list.
for letter in pool:
if results.count(letter) > 1:
# match found
Above, you iterate through the pool variable, which holds all of the possible values. On every loop of that iteration, we check if the current letter that resides inside the pool list exists more than once in the results list. This means that there was a match.
More
You can dynamically increase the player's money count with only a few lines if you keep a list of the possible winnings that correspond with a certain number of matches. For example,
winnings = [100, 200, 300, 400, 500, 600, 700, 800]
Here, 100 is chosen if there are two of the same letter (1 match). If there are three of the same letter (2 matches), 200 is chosen.
player_money = 0
for letter in pool:
result_count = results.count(letter)
player_money += winnings[result_count-2] if result_count > 1 else 0
Above, the line winnings[result_count-2] if result_count > 1 else 0 determines how much the player should receive based off of their matches. We have to subtract 2 from result_count because, remember, python indexing starts from 0, and if there are two of the same letter in the resulting list (1 match), we need to subtract 2 to make it 0, which selects the correct winnings.
If you want to go by your own code then, You can use Counter.
from itertools import Counter
then you can use it like:
Counter([a,b,c,d,e,f]))
to check if any of the values is 2.
Use random.sample() to gather 6 results in a single line.
Then we can simply loop over the sample and check if each draw exists in lottery_results. It also may be better to store the winnings in a dict so we can easily retrieve the amount without too much hassle.
import random
winnings = {6: 100000, 5: 50000, 4: 10000, 3: 1000, 2: 300}
lottery_results = ['x', 'o', 'p', 'k', 'm', 'e', 'a', 'w']
user_numbers = random.sample(lottery_results, 6)
#['m', 'k', 'e', 'a', 'x', 'p']
matches = 0
for draw in user_numbers:
if draw in lottery_results:
matches += 1
print(f'Congrats! You matched {matches} and won ${winnings[matches]}')
#Congrats! You matched 6 and won $100000
You have further issues with the way you have set out to achieve your goal. You're generating the results for the draw from the results of the house. This means you will always match 6.
We can show this by implementing a possible_draws to generate both our results and user draws from. We will use the alphabet as an example.
import string
possible_draws = list(string.ascii_lowercase)
#['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']
lottery_results = random.sample(possible_draws, 8)
#['x', 'h', 'o', 'p', 'j', 'n', 'm', 'c']
user_draws = random.sample(possible_draws, 6)
#['h', 'r', 'u', 't', 'f', 'n']
matches = 0
for draw in user_draws:
if draw in lottery_results:
matches += 1
if matches < 2:
print('No win this time!')
else:
print(f'Congrats! You matched {matches} and won ${winnings[matches]}')
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
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.
I have a string like '102.3k' I would like to convert this string with an engineer prefix notation to a float number.
http://en.wikipedia.org/wiki/Engineering_notation
Allowed prefixes are
posPrefixes = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']
negPrefixes = ['m', 'µ', 'n', 'p', 'f', 'a', 'z', 'y']
k means 10^3
M means 10^6
m means 10^-3
µ means 10^-6
I think I should use regex to do this but I have very few experience with regex.
edit: ideally the solution should also be able to convert any string so '102.3' (without prefix) should also be converted to float
Try this out, no regex needed:
pos_postfixes = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']
neg_postfixes = ['m', 'µ', 'n', 'p', 'f', 'a', 'z', 'y']
num_postfix = n[-1]
if num_postfix in pos_postfixes:
num = float(n[:-1])
num*=10**((pos_postfixes.index(num_postfix)+1)*3)
elif num_postfix in neg_postfixes:
num = float(n[:-1])
num*=10**(-(neg_postfixes.index(num_postfix)+1)*3)
else:
num = float(n)
print(num)
Another thing to note is that in python, it is more common to use underscore variable names than camelcasing, see the pep-8: http://www.python.org/dev/peps/pep-0008/
If you want to control the value, you could try this:
import decimal
posPrefixes = {'k':'10E3', 'M':'10E6', 'G':'10E9', 'T':'10E12', 'P':'10E15', 'E':'10E18', 'Z':'10E21', 'Y':'10E24'}
negPrefixes = {'m':'10E-3', '?':'10E-6', 'n':'10E-9', 'p':'10E-12', 'f':'10E-15', 'a':'10E-18', 'z':'10E-21', 'y':'10E-24'}
val='102.3k'
if val[-1] in posPrefixes.keys():
v = decimal.Decimal(val[:-1])
print v*decimal.Decimal(posPrefixes[val[-1]])
val ='102.3n'
if val[-1] in negPrefixes.keys():
v = decimal.Decimal(val[:-1])
print v*decimal.Decimal(negPrefixes[val[-1]])
Output:
1.0230E+6
1.023e-06