LeetCode/kt/roman-to-integer.kt

73 lines
1.8 KiB
Kotlin
Raw Normal View History

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"
}
}
}