'Convert Integer to Roman Numeral String in Swift

I am looking to take an Integer in Swift and convert it to a Roman Numeral String. Any ideas?



Solution 1:[1]

One could write an extension on Int, similar to the one seen below.

Please note: this code will return "" for numbers less than one. While this is probably okay in terms of Roman Numeral numbers (zero does not exist), you may want to handle this differently in your own implementation.

extension Int {
    var romanNumeral: String {
        var integerValue = self
        var numeralString = ""
        let mappingList: [(Int, String)] = [(1000, "M"), (900, "CM"), (500, "D"), (400, "CD"), (100, "C"), (90, "XC"), (50, "L"), (40, "XL"), (10, "X"), (9, "IX"), (5, "V"), (4, "IV"), (1, "I")]
        for i in mappingList {
            while (integerValue >= i.0) {
                integerValue -= i.0
                numeralString += i.1
            }
        }
        return numeralString
    }
}

Thanks to Kenneth Bruno for some suggestions on improving the code as well.

Solution 2:[2]

Here's my version of an int to roman converter (without nested loop) :

extension Int {
    func toRoman() -> String {
        let conversionTable: [(intNumber: Int, romanNumber: String)] =
            [(1000, "M"),
             (900, "CM"),
             (500, "D"),
             (400, "CD"),
             (100, "C"),
             (90, "XC"),
             (50, "L"),
             (40, "XL"),
             (10, "X"),
             (9, "IX"),
             (5, "V"),
             (4, "IV"),
             (1, "I")]
        var roman = ""
        var remainder = 0
        
        for entry in conversionTable {
            let quotient = (self - remainder) / entry.intNumber
            remainder += quotient * entry.intNumber
            roman += String(repeating: entry.romanNumber, count: quotient)
        }
        
        return roman
    }
}

Solution 3:[3]

This is how you can do it with for loops and dictionaries.

func romanToInt(_ s: String) -> Int {
    
    let numDict: [String: Int] = ["I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000]
    
    let stringArray = Array(s)
    
    var result: Int = 0
    
    for index in 0..<stringArray.count {
        for (k, v) in numDict {
            if String(stringArray[index]) == k {
                if (index + 1) < stringArray.count {
                    if k == String(stringArray[index + 1]) {
                        result += v
                    } else {
                        let nextValue = stringArray[index + 1]
                        for (nextK, nextV) in numDict {
                            if String(nextValue) == nextK {
                                if v < nextV {
                                    result -= v
                                } else {
                                    result += v
                                }
                            }
                        }
                    }
                } else {
                    result += v
                }
            }
        }
    }
    return result
}

Solution 4:[4]

Here is a solution for your question, please check this

func convertRomanToInt(strRoman : String) -> Int {

let arrData = strRoman.map { String($0) }
let dictRomanValue = ["I" : 1, "V" : 5, "X" : 10, "L" : 50, "C" : 100, "D" : 500, "M" : 1000]
var currentValue = 0
var preValue = 0
var ans = 0

for (_,obj) in arrData.enumerated().reversed() {
    _ = dictRomanValue.map({ strName in

        if obj == strName.key {
            currentValue = strName.value
            
            if currentValue < preValue && preValue > 0 {
                ans = ans - preValue + (preValue - currentValue)
                preValue = strName.value
            }else{
                preValue = strName.value
                ans = ans + strName.value
            }
             
        }else{
              ans
        }
    })
}
return ans

}

How to use : It's very simple, you have to call this function

example : convertRomanToInt(strRoman: "LVIII")

Note : it is only work for your number < = 3999.

If you get more number please add greater roman value in "dictRomanValue".

Solution 5:[5]

One more for good measure:

fileprivate let romanNumerals: [String] = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"]
fileprivate let arabicNumerals: [Int] = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]

extension Int {
    var romanRepresentation: String {
        guard self > 0 && self < 4000 else {
            return "Invalid Number"
        }
        var control: Int = self
        return zip(arabicNumerals, romanNumerals)
            .reduce(into: "") { partialResult, ar in
                partialResult += String(repeating: ar.1, count: control/ar.0)
                control = control % ar.0
            }
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Guillaume Ramey
Solution 3 Simran Singh
Solution 4
Solution 5 P. A. Monsaille