On 07/06/2013 10:40 PM, Jim Mooney wrote:
On 6 July 2013 19:09, Dave Angel <[email protected]> wrote:
<SNIP>
If you'd like, I'll post my full version, changed as little as possible from
That would be helpful. The corrections are already four times the size
of the program, and at least three pots of coffee ;')
I hope this is useful. There are lots more places where I might clean
things up, but I wanted to make it as close to yours as possible, so you
could reasonably diff the two.
# Using C:\Python33\python.exe on Win 7 in c:\python33\jimprogs - not
#Windows-specific
# Also works with python 2.7
import sys
import random
#No need to check version, just try to use raw_input. If it's not defined,
# then input should already work
try:
input = raw_input
except NameError as e:
pass #we must be on version 3.0 or larger
try:
range = xrange
except NameError as e:
pass #we must be on version 3.0 or larger
# Data
ones = {'1': 'one', '2': 'two', '3': 'three', '4': 'four', '5': 'five',
'6': 'six',
'7': 'seven', '8': 'eight', '9': 'nine'}
tens = {'2': 'twenty', '3': 'thirty', '4': 'forty', '5': 'fifty', '6':
'sixty',
'7': 'seventy', '8': 'eighty', '9': 'ninety'}
doubles = {'0': 'ten', '1': 'eleven', '2': 'twelve', '3': 'thirteen', '4':
'fourteen',
'5': 'fifteen', '6': 'sixteen', '7': 'seventeen', '8': 'eighteen', '9':
'nineteen'}
powers_of_1000 = (' thousand', ' million', ' billion', ' trillion',
' quadrillion', ' quintillion', ' sextillion', ' septillion', ' octillion',
' nonillion', ' decillion')
'''add these later, and also option for dollars-and-cents ending.
'vigintillion', 'novemdecillion', 'octodecillion', 'septendecillion',
'sexdecillion', 'quindecillion', 'quattuordecillion', 'tredecillion',
'duodecillion', 'undecillion',
'decillion', 'nonillion'
'''
# Functions
def get_raw_input():
'''Enter a positive integer. A list of triplets in the same order will
be returned.
Raise ValueError to loop on non-integer input, or return 'zero'
trigger-value of
'xxx' if all zeroes are entered. If input is okay, strip leading
zeroes, then
zero-pad leftmost triplet to three characters, so all slices are
triplets. Adjust
input for different Python versions.'''
while True:
try:
if sys.version[0:3] == '2.7':
numbers_str = original = raw_input('Enter a positive
integer, space \
separated if desired.')
elif sys.version[0:3] == '3.3':
numbers_str = original = input('Enter a positive
integer, space \
separated if desired.')
else:
print('Python versions 2.7 and 3.3 only supported')
sys.exit()
numbers_str = ''.join(numbers_str.split())
if numbers_str == '' or numbers_str == ' ': raise ValueError
#NO POINT in special-casing zero. It's a perfectly valid
value.
#numbers_int = int(numbers_str)
#if numbers_int == 0:
# print('Zero')
# sys.exit()
numbers_str = str(int(numbers_str)) #normalize it
if len(numbers_str) > 36: raise ArithmeticError
break
except KeyboardInterrupt:
print('Program cancelled by user')
sys.exit()
except ValueError as err:
print(original, "is not an integer.")
continue
except ArithmeticError as err:
print(original, "is too big.\n999...decillion is max:
10**37-1 or 36 chars \
or 12 groups of 3 chars")
return numbers_str
def make_triplets_from_input(numbers_str):
leftpad = "0" * ((-len(numbers_str))%3)
numbers_str = leftpad + numbers_str
#print "numbers_str:", numbers_str
triplets = [numbers_str[x:x+3] for x in range(0,len(numbers_str),3)]
#print "triplets are", triplets
return triplets
def numbers_to_name(triplets):
'''Create a name from each triplet and append the power of ten'''
if triplets == ["000"]:
return "zero"
triplen = len(triplets) - 2
number_name = ''
#print "triplets are", triplets
for triplet in triplets:
#print "triplet is", triplet
triplet_name = ''
first, second, third, last_two = (triplet[0], triplet[1],
triplet[2], triplet[1:])
if triplet == '000':
triplen -= 1
continue
if first > '0':
if last_two == '00': # special case - snip extra space
separator
triplet_name += ones.get(first) + ' hundred'
else:
triplet_name += ones.get(first) + ' hundred '
if second == '0':
if third > '0':
triplet_name += ones.get(third)
elif second == '1':
triplet_name += doubles.get(third)
elif second > '1':
triplet_name += tens.get(second)
if third > '0':
triplet_name += '-' + ones.get(third)
number_name += triplet_name
if triplen > -1:
number_name += powers_of_1000[triplen] + ', '
triplen -= 1
if number_name[-2] == ',':
number_name = number_name[0:-2] # special case - snip
extraneous ending comma
return number_name
def int_name(i):
triplets = make_triplets_from_input(str(i))
return numbers_to_name(triplets)
# Main Program - turn numeric input into number-names
if __name__ == '__main__':
if False:
raw = get_raw_input()
triplets = make_triplets_from_input(raw)
print(numbers_to_name(triplets))
from vegaseat import int2word
def compare_em(i):
a = int_name(i).replace("-", " ").replace(",", "")
b = int2word(i).strip()
if b == "": b = "zero"
if a !=b:
print(i, a, b)
input(" press Enter to continue ")
for i in range(200001):
compare_em(i)
#The following shows a place where the vegaseat code
# starts getting buggy. In particular, it doesn't handle
# numbers bigger than 999octillion or so.
#Note, if we make a range starting at 10**30,
# we get OverflowError, so we fake it
start = 10**30 - 2
for cntr in range(5):
i = start + cntr
compare_em(i)
print "now starting random tests"
for j in range(1000000):
exponent = random.randint(4, 30) #It appears that vegaseat is
buggy beyond 999octillion
i = random.randint(0, 10**exponent-1)
compare_em(i)
--
DaveA
_______________________________________________
Tutor maillist - [email protected]
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor