class Solution { /** * Holds fixed mapping of roman numerals to their respective numeric value. */ private val values = mapOf( 'I' to 1, 'V' to 5, 'X' to 10, 'L' to 50, 'C' to 100, 'D' to 500, 'M' to 1000 ) /** * Represents an accumulator for right fold when turning roman numeral into an integer value. * @property sum Holds the current sum of the accumulator. * @property next Holds the value of the previous roman numeral digit. */ private data class Accumulator(val sum: Int = 0, val next: Int = 0) { /** * @param it Current roman numeral digit. * @return Sign that is to be used when modifying sum of the accumulator. */ private fun sign(it: Int): Int = when (next > it) { true -> -1 false -> 1 } /** * @param it Currently processed roman numeral digit. * @return Correctly updated accumulator. */ fun update(it: Int): Accumulator = copy(sum = sum + sign(it) * it, next = it) } fun romanToInt(s: String): Int = s .map { values[it]!! } .foldRight(Accumulator()) { it, acc -> acc.update(it) } .sum } fun main() { val s = Solution() val tests = mapOf( "I" to 1, "II" to 2, "III" to 3, "IV" to 4, "V" to 5, "VI" to 6, "VII" to 7, "VIII" to 8, "IX" to 9, "X" to 10, "LVIII" to 58, "MCMXCIV" to 1994 ) tests.forEach { (num, i) -> check(s.romanToInt(num) == i) { "$num: ${s.romanToInt(num)} == $i" } } }