Search the Community
Showing results for tags 'roman numerals'.
-
I wrote this Roman numeral conversion function a while ago, but never got round to writing the reverse function. This is a very simple example aimed more at beginners: sometimes you need a break from trying to figure out the more complicated stuff. I decided to post this mini UDF just in case someone might make use of it. The regexp in the _IsRoman() validation function might also be of interest to some of the more advanced members. Maybe it can be improved. #include-once ; #INDEX# ====================================================================================================================== ; Title .........: Roman ; AutoIt Version : 3.3.14.2 ; Language ......: English ; Description ...: Roman numeral conversion and validation. ; Notes .........: Roman numerals range between 1 and 3999. ; Author(s) .....: czardas ; ============================================================================================================================== ; #CURRENT# ==================================================================================================================== ; _IsRoman ; _Roman ; _RomanToDec ; ============================================================================================================================== ; #FUNCTION# =================================================================================================================== ; Name...........: _IsRoman ; Description ...: Tests if a string is a roman numeral. ; Syntax.........: _IsRoman($sRoman) ; Parameters.....; $sRoman - The string to test. ; Return values .: Returns True or False and sets @error to 1 if the parameter is an empty string. ; Author ........: czardas ; ============================================================================================================================== Func _IsRoman($sRoman) If $sRoman = '' Then Return SetError(1, 0, False) $sRoman = StringRegExpReplace($sRoman, '(?i)(\A)(M{0,3})?(CM|DC{0,3}|CD|C{0,3})?(XC|LX{0,3}|XL|X{0,3})?(IX|VI{0,3}|IV|I{0,3})?', '') Return $sRoman = '' EndFunc ;==>_IsRoman ; #FUNCTION# =================================================================================================================== ; Name...........: _Roman ; Description ...: Converts a decimal integer to a roman numeral. ; Syntax.........: _Roman($iInt) ; Parameters.....; $iInt - The integer to convert. ; Return values .: Returns the integer converted to a Roman numeral. ; Sets @error to 1 and returns an empty string if the integer is out of bounds. ; Author ........: czardas ; ============================================================================================================================== Func _Roman($iInt) If Not StringIsInt($iInt) Or $iInt > 3999 Or $iInt < 1 Then Return SetError(1, 0, "") $iInt = Int($iInt) ; in case the string contains leading zeros Local $aNumeral[10][4] = _ [["","","",""], _ ["M","C","X","I"], _ ["MM","CC","XX","II"], _ ["MMM","CCC","XXX","III"], _ ["","CD","XL","IV"], _ ["","D","L","V"], _ ["","DC","LX","VI"], _ ["","DCC","LXX","VII"], _ ["","DCCC","LXXX","VIII"], _ ["","CM","XC","IX"]] Local $iOffset = StringLen($iInt) -4, $sRoman = "", $aDecimal = StringSplit($iInt, "", 2) For $i = 0 To UBound($aDecimal) -1 $sRoman &= $aNumeral[$aDecimal[$i]][$i -$iOffset] Next Return $sRoman EndFunc ;==>_Roman ; #FUNCTION# =================================================================================================================== ; Name...........: _RomanToDec ; Description ...: Converts a roman numeral to a decimal integer. ; Syntax.........: _RomanToDec($sRoman) ; Parameters.....; $sRoman - The Roman numeral to convert. ; Return values .: Returns the Roman numeral converted to an integer. ; Sets @error to 1 and returns an empty string if the Roman numeral is invalid. ; Author ........: czardas ; ============================================================================================================================== Func _RomanToDec($sRoman) If Not _IsRoman($sRoman) Then Return SetError(1, 0, '') Local $aChar = StringSplit($sRoman, '') For $i = 1 To $aChar[0] Switch $aChar[$i] Case 'I' $aChar[$i] = 1 Case 'V' $aChar[$i] = 5 Case 'X' $aChar[$i] = 10 Case 'L' $aChar[$i] = 50 Case 'C' $aChar[$i] = 100 Case 'D' $aChar[$i] = 500 Case 'M' $aChar[$i] = 1000 EndSwitch Next Local $iCount = 0, $iCurr, $iNext For $i = 1 To $aChar[0] $iCurr = $aChar[$i] If $i < $aChar[0] Then $iNext = $aChar[$i +1] If $iNext > $iCurr Then $iCurr = $iNext - $iCurr $i += 1 ; skip the next element EndIf EndIf $iCount += $iCurr Next Return $iCount EndFunc ;==>_RomanToDec Simple Demo #include <Array.au3> #include 'Roman.au3' Local $aRoman[4000] = [3999] For $i = 1 To 3999 $aRoman[$i] = _Roman($i) Next _ArrayShuffle($aRoman, 1) ; shuffle the array starting from Row 1 _ArrayDisplay($aRoman, "Shuffled") RomanSort($aRoman, 1) ; sort the roman numerals by size _ArrayDisplay($aRoman, "Sorted") Func RomanSort(ByRef $aArray, $iStart = Default, $iStop = Default) If Not IsArray($aArray) Or UBound($aArray, 0) <> 1 Then Return SetError(1) ; simple 1D array demo $iStart = ($iStart = Default ? 0 : Int($iStart)) $iStop = ($iStop = Default ? UBound($aArray) -1 : Int($iStop)) If $iStart < 0 Or $iStart > $iStop Or $iStop > UBound($aArray) -1 Then Return SetError(2) ; out of bounds For $i = $iStart To $iStop If Not _IsRoman($aArray[$i]) Then Return SetError(3) ; Roman numerals only [other solutions are beyond the scope of this simple demo] $aArray[$i] = _RomanToDec($aArray[$i]) ; convert to decimal Next _ArraySort($aArray, 0, $iStart, $iStop) ; sort integers For $i = $iStart To $iStop $aArray[$i] = _Roman($aArray[$i]) ; convert back to Roman numerals Next EndFunc ;==> RomanSort