ordinals.py (2225B)
1 from talon import Context, Module, actions, app, ui 2 3 4 def ordinal(n): 5 """ 6 Convert an integer into its ordinal representation:: 7 ordinal(0) => '0th' 8 ordinal(3) => '3rd' 9 ordinal(122) => '122nd' 10 ordinal(213) => '213th' 11 """ 12 n = int(n) 13 suffix = ["th", "st", "nd", "rd", "th"][min(n % 10, 4)] 14 if 11 <= (n % 100) <= 13: 15 suffix = "th" 16 return str(n) + suffix 17 18 19 # The primitive ordinal words in English below a hundred. 20 ordinal_words = { 21 0: "zeroth", 22 1: "first", 23 2: "second", 24 3: "third", 25 4: "fourth", 26 5: "fifth", 27 6: "sixth", 28 7: "seventh", 29 8: "eighth", 30 9: "ninth", 31 10: "tenth", 32 11: "eleventh", 33 12: "twelfth", 34 13: "thirteenth", 35 14: "fourteenth", 36 15: "fifteenth", 37 16: "sixteenth", 38 17: "seventeenth", 39 18: "eighteenth", 40 19: "nineteenth", 41 20: "twentieth", 42 30: "thirtieth", 43 40: "fortieth", 44 50: "fiftieth", 45 60: "sixtieth", 46 70: "seventieth", 47 80: "eightieth", 48 90: "ninetieth", 49 } 50 tens_words = "zero ten twenty thirty forty fifty sixty seventy eighty ninety".split() 51 52 # ordinal_numbers maps ordinal words into their corresponding numbers. 53 ordinal_numbers = {} 54 ordinal_small = {} 55 for n in range(1, 100): 56 if n in ordinal_words: 57 word = ordinal_words[n] 58 else: 59 (tens, units) = divmod(n, 10) 60 assert 1 < tens < 10, "we have already handled all ordinals < 20" 61 assert 0 < units, "we have already handled all ordinals divisible by ten" 62 word = f"{tens_words[tens]} {ordinal_words[units]}" 63 64 if n <= 20: 65 ordinal_small[word] = n 66 ordinal_numbers[word] = n 67 68 69 mod = Module() 70 ctx = Context() 71 mod.list("ordinals", desc="list of ordinals") 72 mod.list("ordinals_small", desc="list of ordinals small (1-20)") 73 74 ctx.lists["self.ordinals"] = ordinal_numbers.keys() 75 ctx.lists["self.ordinals_small"] = ordinal_small.keys() 76 77 78 @mod.capture(rule="{self.ordinals}") 79 def ordinals(m) -> int: 80 """Returns a single ordinal as a digit""" 81 return int(ordinal_numbers[m[0]]) 82 83 84 @mod.capture(rule="{self.ordinals_small}") 85 def ordinals_small(m) -> int: 86 """Returns a single ordinal as a digit""" 87 return int(ordinal_numbers[m[0]])