I am creating a number-to-word translator and have it working with one exception.
I am having trouble accounting for zeros, for example if the number 4056 is typed in 'four thousand zero hundred fifty six' is output. Furthermore if 50 is typed in 'fifty zero' is output.
What I have so far is included below:
def convert(number_str):
d1 = {0: 'zero',1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', \
6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten', \
11: 'eleven', 12: 'twelve', 13: 'thirteen', 14: 'fourteen', \
15: 'fifteen', 16: 'sixteen', 17: 'seventeen', 18: 'eighteen', 19: 'nineteen'}
l2 = ['twenty','thirty','fourty','fifty','sixty','seventy','eighty','ninety']
if (int(number_str) >= 1) and (int(number_str) < 19):
return(d1[number_str])
elif (int(number_str) >= 20) and (int(number_str) <99):
tens, single = divmod(number_str, 10)
return l2[tens-2] + " " + d1[single]
elif (int(number_str) >= 100) and (int(number_str) <999):
hundreds, tens1 = divmod(number_str, 100)
tens, single = divmod(tens1,10)
return(d1[hundreds]+' hundred '+l2[tens-2]+" "+d1[single])
elif (int(number_str) >= 1000) and (int(number_str) <9999):
thousands, hundreds1 = divmod(number_str,1000)
hundreds, tens1 = divmod(hundreds1,100)
tens, single = divmod(tens1,10)
return(d1[thousands]+' thousand '+d1[hundreds]+' hundred '+l2[tens-2]+" "+d1[single])
def main():
user_input = input('> ')
while user_input != 'quit':
print(convert(int(user_input)))
user_input = input('> ')
main()
What logic can I add in order to better handle the use of zeros to bolster this program? Thanks in advance!
You need to add special conditions for zero. For example, the problem with 50 can be checked with an if statement:
lif (int(number_str) >= 20) and (int(number_str) <99):
tens, single = divmod(number_str, 10)
if single == 0:
return l2[tens-2]
else:
return l2[tens-2] + " " + d1[single]
You can write a similar if to deal with a 0 in the hundreds place.
The numbering system that we use in language developed well before the use of the Arabic numbering system that uses zeros effectively as a placeholder.
I'd imagine some logic in which any zero is not commented upon would work. Purely view it as a place holder to make the numbers to the left a higher 10^n value.
def convert(number_str):
d1 = {0: '',1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', \
6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten', \
11: 'eleven', 12: 'twelve', 13: 'thirteen', 14: 'fourteen', \
15: 'fifteen', 16: 'sixteen', 17: 'seventeen', 18: 'eighteen', 19: 'nineteen'}
# Changed zero to an empty string
l2 = ['twenty','thirty','fourty','fifty','sixty','seventy','eighty','ninety']
if int(number_str) == 0: # Catches the unique case when zero is mentioned
return('zero')
elif (int(number_str) >= 1) and (int(number_str) < 19):
return(d1[number_str])
elif (int(number_str) >= 20) and (int(number_str) <=99):
tens, single = divmod(number_str, 10)
return l2[tens-2] + " " + d1[single]
elif (int(number_str) >= 100) and (int(number_str) <=999):
hundreds, tens1 = divmod(number_str, 100)
tens, single = divmod(tens1,10)
return(d1[hundreds]+' hundred '+((l2[tens-2]+" "+d1[single]) if tens > 1 else d1[tens*10+single]))
# Added a conditional statement above to deal with numbers ending
# in a number less than 20
elif (int(number_str) >= 1000) and (int(number_str) <=9999):
thousands, hundreds = divmod(number_str,1000)
return(d1[thousands]+' thousand '+ convert(hundreds))
# Added a recursive call to save code
def main():
user_input = input('> ')
while user_input != 'quit':
print(convert(int(user_input)))
user_input = input('> ')
main()
Note that it is edited in two places. Firstly to make the zero an empty string, then to catch the condition where it is simply zero.
Related
I am trying to ask and answer the question "How old are you?" and then store the user's response to that question and print out the answer. Here is what I have done so far:
age = input("How old are you?")
print('How old are you?', word)
agea = input("sixty")
I cannot get it to store sixty and print it out as a word. I would like even better to not only do so but be able to store and print the age as a number. Thus far, the system only prints the answer:
How old are you?
Please do what you can to help.
So, just for adding you some explanations about your code:
age = input("How old are you?") # Read the input from the user and save it to the 'age' variable
print('How old are you?', word) # Print message, using 'word' as a variable.
# This should throw an error message since 'word' is not assigned anywhere above.
agea = input("sixty") # Print the 'sixty' message, read the user input and save it into 'agea' variable.
# What I imagine is that you have typing error here. Do you mean 'age' instead of 'agea'?
Correction suggestion
age = input("How old are you?") # Print message and wait for input from the user,
# assigning it to 'age' variable
print(f"You are {age} years old") # Print the message replacing {age} with the variable content.
In python, there's no meaning to variable types like word. Numbers are whole or decimal, regardless of their size. There are some exceptions to that rule, but that is the general case.
Now, to your question - the function input() can also print your string to the screen so the user can know he has to enter his input.
what you need to do in order to get the user's age and then print it is:
age = input("How old are you?")
print("you are ", age, " years old")
this will print the user's age. if you want to convert the input into an int just write
age = int(input("How old are you?"))
but be careful with this because if the user doesn't input an integer you will get an exception. In order to avoid that do:
age = input("How old are you?")
if age.isdigit():
print("you are ", age, " years old")
age = int(age)
else:
print("you must input a number!)
You can use a Dictionary, like this:
num2words = {1: 'One', 2: 'Two', 3: 'Three', 4: 'Four', 5: 'Five', 6: 'Six', 7: 'Seven', 8: 'Eight', 9: 'Nine', 10: 'Ten',
11: 'Eleven', 12: 'Twelve', 13: 'Thirteen', 14: 'Fourteen', 15: 'Fifteen', 16: 'Sixteen', 17: 'Seventeen', 18: 'Eighteen',
19: 'Nineteen', 20: 'Twenty', 30: 'Thirty', 40: 'Forty', 50: 'Fifty', 60: 'Sixty', 70: 'Seventy', 80: 'Eighty',
90: 'Ninety', 0: 'Zero'}
def n2w(n):
try:
print (num2words[n])
except KeyError:
try:
print (num2words[n-n%10] + " " + num2words[n%10].lower())
except KeyError:
print ('Number out of range')
if __name__ == "__main__":
a = input("Type you age using numbers:")
n2w(int(a))
In this case, i picked the number as a integer and transformed it in a integer. The input and output was:
Type you age using numbers:55
Fifty five
When setting a variable to an input, the value of the variable becomes what the user had input into the "How old are you? " statement. In this case, if someone inputted "18" from the prompt, then age would equal 18 and it would print You are 18 years old.
age = input("How old are you? ")
print("You are " + age + " years old.")
If you want the user to input a string such as "sixty" and have the result be something like You are sixty years old., then you could make it so that the input value can only accept string values like so:
age = input("How old are you? ")
if age.isdigit():
print("Invalid")
else:
print("You are " + age + " years old.")
# or # print(f"You are {age} years old")
So the program should take a number and then should print this number using text.
print("Enter your number")
Number = int(input())
def number_to_text_ones(ones):
if ones == 1:
print("one")
elif ones == 2:
print("two")
elif ones == 3:
print("three")
elif ones == 4:
print("four")
elif ones == 5:
print("five")
elif ones == 6:
print("six")
elif ones == 7:
print("seven")
elif ones == 8:
print("eight")
elif ones == 9:
print("nine")
def number_to_text_tens(tens):
if tens == 2:
print("twenty ")
elif tens == 3:
print("thirty ")
elif tens == 4:
print("fourry ")
elif tens == 5:
print("fifty ")
elif tens == 6:
print("sixty ")
elif tens == 7:
print("seventy ")
elif tens == 8:
print("eighty ")
elif tens == 9:
print("ninety ")
def number_to_text_hundreds(hundreds):
if hundreds == 1:
print("one hundred")
elif hundreds == 2:
print("two hundreds")
elif hundreds == 3:
print("three hundreds")
elif hundreds == 4:
print("four hundreds")
elif hundreds == 5:
print("five hundreds")
elif hundreds == 6:
print("six hundreds")
elif hundreds == 7:
print("seven hundreds")
elif hundreds == 8:
print("eight hundreds")
elif hundreds == 9:
print("nine hundreds")
if Number == 0:
print("zero")
elif Number == 10:
print("ten")
elif Number == 11:
print("eleven")
elif Number == 12:
print("twelve")
elif Number == 13:
print("thirteen")
elif Number == 14:
print("fourteen")
elif Number == 15:
print("fifteen")
elif Number == 16:
print("sixteen")
elif Number == 17:
print("seventeen")
elif Number == 18:
print("eighteen")
elif Number == 19:
print("nineteen")
if Number < 10:
Result = Number % 10
number_to_text_ones(Result)
elif (Number >= 20 and Number < 100):
First = Number // 10
Second = (Number - (First * 10)) % 10
Result = First * 10 + Second
number_to_text_tens(First)
number_to_text_ones(Second)
elif (Number >= 100 and Number < 1000):
First = Number // 100
Second = (Number - (First * 100)) // 10
Third = (Number - (First * 100) - (Second * 10)) % 10
Result = First * 100 + Second * 10 + Third
number_to_text_hundreds(First)
number_to_text_tens(Second)
number_to_text_ones(Third)
The problem is when I input, say, 895 my output will be:
eight hundreds
ninety
five
Few questions I have:
How to make my output look better?
Is there any way to get rid of those if statements and use something more efficient? Something like switch/case
Here are the answers:
print function has an optional parameter end which specifies what will be written at the end of the string you are printing. Default is new line ('\n'). You would like to use
print('something', end=' ')
Nicer than that would be to first build a string with the name of entire number and the use print only once at the end.
A nice way to solve this is with dictionary, e.g.:
name = {1: "one hundred",
2: "two hundreds",
3: "three hundreds"}[hundreds]
I suspect there is a library for this but I'd refactor to use the following pattern
ones_text = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
def number_to_text_ones(number):
return ones_text[number - 1]
You should use dictionaries as it will reduce the lines of code (if-else conditions will no more be there just a return statement would be sufficient ) and will give your code a better look also execution time will decrease because using if-else condition the program checks each every condition specified, So dictionaries will make help u alot
And for printing your output in one line this one is a better
print(number_to_text_hundreds(First) + number_to_text_tens(Second) + number_to_text_ones(Third))
number_to_text_hundereds , number_to_text_tens and number_to_text_ones returns a value corresponding to value passed to function
I suggest you using lists of strings as follows:
print("Enter your number")
Number = int(input())
units = ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
teens = ["ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"]
tens = ['', '', "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]
h = Number // 100
t = (Number % 100) // 10
u = (Number % 10)
result = []
if h == 0:
pass
elif h == 1:
result.append('one hundred')
else:
result.append(units[h] + ' hundreds')
if (t == 0):
if (u != 0):
result.append(units[u])
elif (h == 0):
result = ['zero']
elif (t == 1):
result.append(teens[u])
else:
result.append(tens[t])
if (u != 0):
result.append(units[u])
result = ' '.join(result)
print(result)
# input = 895 : result = 'eight hundreds ninety five'
# input = 507 : result = 'five hundreds seven'
# input = 120 : result = 'one hundred twenty'
# input = 071 : result = 'seventy one'
# input = 16 : result = 'sixteen'
# input = 0 : result = 'zero'
I have a multiple condition:
if you == 1 or you == 2:
one.put(argument)
elif you == 3:
return None
elif you == 4:
two.put(argument)
elif you == 5:
three.put(argument)
elif you == 6:
four.put(argument)
elif you == 7:
five.put(argument)
elif you == 8:
six.put(argument)
elif you == 9:
seven.put(argument)
elif you == 10:
eight.put(argument)
elif you == 11:
nine.put(argument)
elif you == 12:
ten.put(argument)
I want to change it to use a dictionary, but I get exceptions in:
if you == 1 or you == 2:
one.put(argument)
elif you == 3:
return None
What is the best way to do this?
This will work:
actions = {1: one.put,
2: one.put,
3: None,
4: two.put,
# ....
}
action = actions.get(you)
if callable(action): # guards against non existing "you"'s or if you == 3
action(argument)
# can also do this:
# if action is not None:
# action(argument)
# or that..
# try:
# action(argument)
# except TypeError: # if action is None we'll get an exception, NoneType isn't callable
# pass
Store the varying part of your expression in a dictionary.
I put 3 in there as well, just for completeness, and possible later use.
put_dict = {
1: one, 2: one,
3: None
4: two, 5: three,
6: four, 7: five,
8: six, 9: seven,
10: eight, 11: nine,
12: ten
}
if you == 3:
return None
else:
put_dict[you].put(argument)
I'd create a sink for the values you don't want:
class Sink:
#staticmethod
def put(object):
pass
put_dict = {
1: one, 2: one,
3: Sink,
4: two, 5: three,
6: four, 7: five,
8: six, 9: seven,
10: eight, 11: nine,
12: ten}
def function(you, argument)
put_dict[you].put(argument)
So I have written a program in python to try and convert a number typed into the letter version of that number. Ex: 323 -> three hundred twenty-three
The problem I am having is that the one of the variables is not displaying the correct value when the process is complete and the output is displayed. The desired output would look something like this:
Enter a number under 999: 323
323 -> three hundred twenty-three
but instead looks like this:
Enter a number under 999: 323
23 -> three hundred twenty-three
If anyone can help me figure this out, I would greatly appreciate it. Here is my code:
from __future__ import print_function, division
import sys
input = raw_input
n = int(input("Enter a number under 999: "))
if n >= 999:
print("Well, you didn't follow directions.")
sys.exit(1)
word = ""
hundred = n//100
if hundred == 1:
word += "one hundred"
elif hundred == 2:
word += "two hundred"
elif hundred == 3:
word += "three hundred"
elif hundred == 4:
word += "four hundred"
elif hundred == 5:
word += "five hundred"
elif hundred == 6:
word += "six hundred"
elif hundred == 7:
word += "seven hundred"
elif hundred == 8:
word += "eight hundred"
elif hundred == 9:
word += "nine hundred"
if hundred > 0:
word += " "
n = n%100
if n == 10:
word += ' ten'
elif n == 11:
word += ' eleven'
elif n == 12:
word += ' twelve'
elif n == 13:
word += ' thirteen'
elif n == 14:
word += ' fourteen'
elif n == 15:
word += ' fifteen'
elif n == 16:
word += ' sixteen'
elif n == 17:
word += ' seventeen'
elif n == 18:
word += ' eighteen'
elif n == 19:
word += ' nineteen'
else:
ones = n%10
tens = n//10
if tens == 2:
word += "twenty"
elif tens == 3:
word += "thirty"
elif tens == 4:
word += "fourty"
elif tens == 5:
word += "fifty"
elif tens == 6:
word += "sixty"
elif tens == 7:
word += "seventy"
elif tens == 8:
word += "eighty"
elif tens == 9:
word += "ninety"
if tens > 0 and ones > 0:
word += '-'
if ones == 1:
word += 'one'
elif ones == 2:
word += 'two'
elif ones == 3:
word += 'three'
elif ones == 4:
word += 'four'
elif ones == 5:
word += 'five'
elif ones == 6:
word += 'six'
elif ones == 7:
word += 'seven'
elif ones == 8:
word += 'eight'
elif ones == 9:
word += 'nine'
print("{} -> {}".format(n, word))
Oh and btw, My class is learning python 3 while using a python 2 interpreter so that's why the code has some weird aspects to it.
since
n = n%100
mutates "n", you need to "save" the value of "n" first. the most simple method would be:
after declaring
n = int(input("Enter a number under 999: "))
set another variable to n
n = int(input("Enter a number under 999: "))
num = n
then replace
print("{} -> {}".format(n, word))
with
print("{} -> {}".format(num, word))
Change your code to
n = int(input("Enter a number under 999: "))
user_number = n
(...)
print("{} -> {}".format(user_number, word))
Every time you do operations on n you modify it:
n = n%100
So just save it in another variable before modifying it (user_number) and print it at the end.
write code to simulate the game for one player and calculate the number of dice throws required to finish a game. The user should be allowed to specify the number of games simulated and the code should calculate the average number of dice throws per game.
#Snakes and Ladders simulation
import random #importing the random function to be able to use it later on
counterposition = 0 #setting counterposition and diceroll to 0
currentDiceroll = 0
def diceroll (): #when user rolls the 1-6 dice this does it randomly
return random.randint (1,6)
userInput = int(input("How many games would you like to play snakes and ladders?"))
for i in range (userInput):
currentDiceroll = diceroll()
print("The currentDiceroll is", currentDiceroll)
if counterposition == 1: #all the if statements show what happens if the one player lands on a snake or a ladder
counterposition = counterposition + 37
if counterposition == 4:
counterposition = counterposition + 10
if counterposition == 9:
counterposition = counterposition + 22
if counterposition == 21:
counterposition = counterposition + 21
if counterposition == 28:
counterposition = counterposition + 56
if counterposition == 51:
counterposition = counterposition + 16
if counterposition == 72:
counterposition = counterposition + 19
if counterposition == 80:
counterposition = counterposition + 19
if counterposition == 17:
counterposition = counterposition - 10
if counterposition == 54:
counterposition = counterposition - 20
if counterposition == 63:
counterposition = counterposition - 4
if counterposition == 64:
counterposition = counterposition - 4
if counterposition == 87:
counterposition = counterposition - 51
if counterposition == 92:
counterposition = counterposition - 19
if counterposition == 95:
counterposition = counterposition - 20
if counterposition == 98:
counterposition = counterposition - 19
if counterposition >= 100:
print ("Congratulations end of game")
counterposition = counterposition + currentDiceroll
print("the counter position is", counterposition)
The code that you have written only rolls the dice one time. You need to keep rolling until you have won the game. It might be best to create a function that plays the game one time and returns the number of dice rolls needed.
def playGame():
counterPosition = 0
numberOfRolls = 0
while (counterPosition < 100):
numberOfRolls += 1
currentDiceroll = diceroll()
print("The currentDiceroll is", currentDiceroll)
counterPosition += currentDiceroll
# your if statements go here
return numberOfRolls
Then you can call this function however many times you want.
totalDiceRolls = 0
for i in range(userInput):
totalDiceRolls += playGame()
avgRolls = totalDiceRolls / userInput
It wasn't what you explicitly asked about, but your code is a bit repetitious with all of those if statements. One thing you can do is to conceptualize a move as consisting of moving by the amount given by the die roll, followed by a "bump" which is 0 for most squares, a positive number for squares where a ladder starts, and a negative number for squares at the top of a snake. A dictionary is the natural data structure for the bumps, with only the negative and positive bumps stored explicitly. The dictionary method get() can be used to either return the bump if the final square is a key in the dictionary or return the default 0 if it isn't. Then a single game simulation could simply be:
bump = {1:37, 4:10, 9:22, 21:21, 28:56, 51:16, 72:19, 80:19, 17:-10, 54: -20, 63: -4, 64: -4, 87: -51, 92: -19, 95:-20, 98: -19}
def simulateGame():
pos = 0
count = 0
while pos < 100:
roll = random.randint(1,6)
pos += roll + bump.get(pos,0)
count += 1
return count
And the expected number of rolls can be estimated by:
def expectedRolls(trials = 10000):
return sum(simulateGame() for i in range(trials))/trials
Some of the above might involve things that you haven't seen yet, but when you find yourself writing long sections of almost identical code you should if at all possible streamline it. Repetitious code is not pythonic.
If you haven't studied dictionaries yet but have studied lists, you could make bump an array with 101 items initialized like: bump = [0]*101 (101 zeros) and then have a series of assignment like bump[1] = 37, bump[4] = 10, etc. And then replace the line:
pos += roll + bump.get(pos,0)
by the even simpler line:
pos += roll + bump[0]
which in effect says "add to the current position the roll plus any resulting bump"
The code
def expectedRolls(trials = 10000):
return sum(simulateGame() for i in range(trials))/trials
uses a generator expression inside of the sum function. If you aren't familiar with those yet, you can add them in an explicit loop as in the excellent answer of A. Sokol