| 1 | 1 | def say(number: int) -> str: |
| 2 | | pass |
| 2 | if number < 0 or number > 999999999999: |
| 3 | raise ValueError("input out of range") |
| 4 | |
| 5 | # Edge Case: number is zero |
| 6 | if number == 0: |
| 7 | return "zero" |
| 8 | |
| 9 | # Define word mappings |
| 10 | ones = ["", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", |
| 11 | "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", |
| 12 | "seventeen", "eighteen", "nineteen"] |
| 13 | |
| 14 | tens = ["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"] |
| 15 | |
| 16 | scales = ["", "thousand", "million", "billion"] |
| 17 | |
| 18 | # Edge Case: numbers less than 20 |
| 19 | if number < 20: |
| 20 | return ones[number] |
| 21 | |
| 22 | def convert_under_thousand(n): |
| 23 | """Convert a number under 1000 to words""" |
| 24 | result = [] |
| 25 | |
| 26 | # Handle hundreds place |
| 27 | if n >= 100: |
| 28 | result.append(ones[n // 100]) |
| 29 | result.append("hundred") |
| 30 | n %= 100 |
| 31 | |
| 32 | # Handle tens and ones place |
| 33 | if n >= 20: |
| 34 | tens_part = tens[n // 10] |
| 35 | ones_part = ones[n % 10] |
| 36 | if ones_part: |
| 37 | result.append(tens_part + "-" + ones_part) |
| 38 | else: |
| 39 | result.append(tens_part) |
| 40 | elif n > 0: # Edge Case: numbers between 1 and 19 |
| 41 | result.append(ones[n]) |
| 42 | |
| 43 | return " ".join(result) |
| 44 | |
| 45 | # Break number into groups of three digits |
| 46 | groups = [] |
| 47 | temp_number = number |
| 48 | while temp_number > 0: |
| 49 | groups.append(temp_number % 1000) |
| 50 | temp_number //= 1000 |
| 51 | |
| 52 | # Edge Case: empty groups (should not happen with valid input) |
| 53 | if not groups: |
| 54 | return "zero" |
| 55 | |
| 56 | parts = [] |
| 57 | for i, group in enumerate(groups): |
| 58 | if group != 0: |
| 59 | group_words = convert_under_thousand(group) |
| 60 | if i > 0: |
| 61 | group_words += " " + scales[i] |
| 62 | parts.append(group_words) |
| 63 | |
| 64 | # Edge Case: parts might be empty (handled by earlier checks, but for safety) |
| 65 | if not parts: |
| 66 | return "zero" |
| 67 | |
| 68 | return " ".join(reversed(parts)) |
| 69 | |
| 70 | # Handled Edge Cases: negative numbers, numbers greater than 999,999,999,999, zero, numbers less than 20, numbers between 1 and 19, empty groups, empty parts |