Skip to content

Instantly share code, notes, and snippets.

@mdenson-dayspring
Last active March 31, 2022 19:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mdenson-dayspring/e541a5bf707a204647bd8d74c1086c4b to your computer and use it in GitHub Desktop.
Save mdenson-dayspring/e541a5bf707a204647bd8d74c1086c4b to your computer and use it in GitHub Desktop.
A program that takes an array of numbers and returns the spelled-out cardinal and ordinal forms of those numbers.
#
# A program that takes an array of numbers and returns the spelled-out cardinal and ordinal forms of those numbers.
# Includes framework to allow use as a Lambda function.
#
# Example usage:
# $ echo "{"numbers": [0, 1, 2, 3, 4, 5, 11, 65, 100, 101, 277, 23456, 8007006005004003]}" | python3 spell_number.py
# {"ordinals": ["zero", "one", "two", "three", "four", "five", "eleven", "sixty five", "one hundred", \
# "one hundred and one", "two hundred seventy seven", "twenty three thousand four hundred fifty six", \
# "eight quadrillion seven trillion six billion five million four thousand and three"], \
# "cardinals": ["zeroth", "first", "second", "third", "fourth", "fifth", "eleventh", "sixty fifth", "one hundredth", \
# "one hundred and first", "two hundred seventy seventh", "twenty three thousand four hundred fifty sixth", \
# "eight quadrillion seven trillion six billion five million four thousand and third"]}
#
# Copyright 2022 by Matthew Denson <mdenson@dayspringpartners.com>
#
import sys
import math
import json
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def spell_group(digits):
units = ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
teens = ['ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen']
decades = ['', '', 'twenty', 'thirty', 'fourty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety']
build = ''
while len(digits) < 3:
digits.append(0)
[ones, tens, hundreds] = digits
if hundreds > 0:
build = build + ' ' + units[hundreds] + ' hundred'
if tens == 0 and hundreds > 0 and ones > 0:
build = build + ' and ' + units[ones]
elif tens == 1:
build = build + ' ' + teens[ones]
else:
build = build + ' ' + decades[tens] + ' ' + units[ones]
return build.strip()
def spell_ordinal(number):
groups = ['', 'thousand', 'million', 'billion', 'trillion', 'quadrillion', 'quintillion', 'sextillion', 'septillion', 'octillion', 'nontillion']
# special case for zero
if number == 0:
return 'zero'
digits = []
remainder = number
while remainder > 0:
digits.append(remainder % 10)
remainder = math.floor(remainder / 10)
if len(digits) == 4 and digits[2] > 0 and digits[0] == 0 and digits[1] == 0:
retString = spell_group(digits[2:]) + " hundred"
else:
groupNum = 0
retString = ''
while len(digits) > 0:
group_spelled = spell_group(digits[:3])
groupString = groups[groupNum]
if len(groupString) > 0:
group_spelled = group_spelled + ' ' + groupString
retString = group_spelled.strip() + ' ' + retString
groupNum = groupNum + 1
digits = digits[3:]
return retString.strip()
def to_cardinal(ordinal):
if len(ordinal) == 0:
return ''
words = ordinal.rsplit(' ', 1)
if words[0] == ordinal:
prefix = ''
word = words[0]
else:
prefix = words[0] + ' '
word = words[1]
lookup = {'one': 'first', 'two': 'second', 'three': 'third', 'four': 'fourth', 'five': 'fifth', 'six': 'sixth', 'seven': 'seventh', 'eight': 'eighth', 'nine':'ninth'}
if word in lookup:
newword = lookup[word]
else:
# handle 'y' at end of some words
if word[-1] == 'y':
word = word[:-1] + 'i'
newword = word + 'th'
return prefix + newword
def spell_number(event, context):
if 'body' in event.keys():
# this is the case in aws
body = json.loads(event.get('body'))
inAws = True
logger.info("Live mode")
else:
body = event
inAws = False
logger.info("DEV mode")
ordinals = list(map(spell_ordinal, body['numbers']))
response_body = {
'ordinals': ordinals,
'cardinals': list(map(to_cardinal, ordinals))
}
if inAws:
response = {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json'
},
'body': json.dumps(response_body)
}
response['isBase64Encoded'] = False
else:
response = response_body
return response
if __name__ == '__main__':
print(json.dumps(spell_number(json.load(sys.stdin), {})))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment