diff --git a/commands/conversions/roman-numerals b/commands/conversions/roman-numerals new file mode 100644 index 000000000..360035e57 --- /dev/null +++ b/commands/conversions/roman-numerals @@ -0,0 +1,150 @@ +#!/usr/bin/env python3 + +# Required parameters: +# @raycast.schemaVersion 1 +# @raycast.title Roman Numerals +# @raycast.packageName Conversions +# @raycast.description Converts Roman numerals (I, V, X, etc.) into Arabic numerals (1, 2, 3, etc.) +# @raycast.mode compact + +# Optional parameters: +# @raycast.icon 🔢 + +# Documentation: +# @raycast.author Kailash Yellareddy +# @raycast.authorURL https://github.com/kyellareddy + +# @raycast.argument1 { "type": "text", "placeholder": "Roman Numeral", "optional": false } +# @raycast.argument2 { "type": "dropdown", "placeholder": "Speak", "data": [{ "title": "Don't Speak", "value": "no" }, { "title": "Speak", "value": "yes" }] } + +import sys +import subprocess + +roman_numeral = sys.argv[1] if len(sys.argv) > 1 else "" +speak_output = sys.argv[2] if len(sys.argv) > 2 else "no" +r = roman_numeral.upper() + +def speak(text): + if speak_output == "yes": + subprocess.run(["say", text]) + +def speak_roman(roman): + return " ".join(roman) + +def value(ch: str): + if ch.upper() == 'I': + return 1 + if ch.upper() == 'V': + return 5 + if ch.upper() == 'X': + return 10 + if ch.upper() == 'L': + return 50 + if ch.upper() == 'C': + return 100 + if ch.upper() == 'D': + return 500 + if ch.upper() == 'M': + return 1000 + return 0 + +def decimalToRoman(n: int): + vals = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1] + syms = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", + "X", "IX", "V", "IV", "I"] + + out = [] + i = 0 + + while n > 0: + while n >= vals[i]: + out.append(syms[i]) + n -= vals[i] + i += 1 + + return "".join(out) + +def romanToDecimal(s): + res = 0 + i = 0 + + while i < len(s): + + s1 = value(s[i]) + + if s1 == 0: + return "That is not a valid Roman numeral." + + if i + 1 < len(s): + + s2 = value(s[i + 1]) + + if s2 == 0: + return "That is not a valid Roman numeral." + + if s1 >= s2: + res = res + s1 + i = i + 1 + else: + res = res + s2 - s1 + i = i + 2 + + else: + res = res + s1 + i = i + 1 + + # Convert the result back into a Roman numeral + # and compare it with the original. + if decimalToRoman(res) != s: + return "That is not a valid Roman numeral." + + return res + +if len(sys.argv) < 2: + message = "Usage: python script.py ROMAN_NUMERAL_OR_NUMBER" + print(message) + speak(message) + +else: + user_input = sys.argv[1].strip() + + # English numeral → Roman numeral + if user_input.isdigit(): + + num = int(user_input) + + if num > 3999: + warning = ( + "That number is too large for standard Roman numerals, " + "which max out at 3999." + ) + + print(warning) + speak(warning) + + else: + roman_result = decimalToRoman(num) + + message = f"{num} is equal to {roman_result}" + spoken_message = f"{num} is equal to {speak_roman(roman_result)}" + + print(message) + speak(spoken_message) + # Roman numeral → English numeral + else: + + roman = user_input.upper() + result = romanToDecimal(roman) + + if isinstance(result, str): + + print(result) + speak(result) + + else: + + message = f"{roman} is equal to {result}" + spoken_message = f"{speak_roman(roman)} is equal to {result}" + + print(message) + speak(spoken_message)