From: Scott Gasch Date: Fri, 14 Oct 2022 16:25:50 +0000 (-0700) Subject: Adds function to write out an integer longhand. X-Git-Url: https://wannabe.guru.org/gitweb/?a=commitdiff_plain;h=8862fd84dbe1146aa0b4cd2fd3a90f374a6d6246;p=pyutils.git Adds function to write out an integer longhand. --- diff --git a/src/pyutils/string_utils.py b/src/pyutils/string_utils.py index 69ab837..f82ec4b 100644 --- a/src/pyutils/string_utils.py +++ b/src/pyutils/string_utils.py @@ -177,7 +177,7 @@ NUM_SUFFIXES = { "K": (1024**1), } -units = [ +UNIT_WORDS = [ "zero", "one", "two", @@ -200,7 +200,7 @@ units = [ "nineteen", ] -tens = [ +TENS_WORDS = [ "", "", "twenty", @@ -213,16 +213,19 @@ tens = [ "ninety", ] -scales = ["hundred", "thousand", "million", "billion", "trillion"] +scales = ["hundred", "thousand", "million", "billion", "trillion", "quadrillion"] NUM_WORDS = {} NUM_WORDS["and"] = (1, 0) -for i, word in enumerate(units): +for i, word in enumerate(UNIT_WORDS): NUM_WORDS[word] = (1, i) -for i, word in enumerate(tens): +for i, word in enumerate(TENS_WORDS): NUM_WORDS[word] = (1, i * 10) for i, word in enumerate(scales): - NUM_WORDS[word] = (10 ** (i * 3 or 2), 0) + if i == 0: + NUM_WORDS[word] = (100, 0) + else: + NUM_WORDS[word] = (10 ** (i * 3), 0) NUM_WORDS['score'] = (20, 0) @@ -524,6 +527,52 @@ def number_string_to_integer(in_str: str) -> int: return result + current +def integer_to_number_string(num: int) -> str: + """ + Opposite of number_string_to_integer; convert a number to a written out + longhand format. + + >>> integer_to_number_string(9) + 'nine' + + >>> integer_to_number_string(42) + 'forty two' + + >>> integer_to_number_string(123219982) + 'one hundred twenty three million two hundred nineteen thousand nine hundred eighty two' + + """ + + if num < 20: + return UNIT_WORDS[num] + if num < 100: + ret = TENS_WORDS[num // 10] + leftover = num % 10 + if leftover != 0: + ret += ' ' + UNIT_WORDS[leftover] + return ret + + # If num > 100 go find the highest chunk and convert that, then recursively + # convert the rest. NUM_WORDS contains items like 'thousand' -> (1000, 0). + # The second item in the tuple is an increment that can be ignored; the first + # is the numeric "scale" of the entry. So find the greatest entry in NUM_WORDS + # still less than num. For 123,456 it would be thousand. Then pull out the + # 123, convert it, and append "thousand". Then do the rest. + scales = {} + for name, val in NUM_WORDS.items(): + if val[0] <= num: + scales[name] = val[0] + scale = max(scales.items(), key=lambda _: _[1]) + + # scale[1] = numeric magnitude (e.g. 1000) + # scale[0] = name (e.g. "thousand") + ret = integer_to_number_string(num // scale[1]) + ' ' + scale[0] + leftover = num % scale[1] + if leftover != 0: + ret += ' ' + integer_to_number_string(leftover) + return ret + + def is_decimal_number(in_str: str) -> bool: """ Args: