fold with repeat

Roman Numerals
Roman Numerals in Kotlin
object RomanNumerals {

    fun value(n: Int) =
            listOf(
                            1000 to "M",
                            900 to "CM",
                            500 to "D",
                            400 to "CD",
                            100 to "C",
                            90 to "XC",
                            50 to "L",
                            40 to "XL",
                            10 to "X",
                            9 to "IX",
                            5 to "V",
                            4 to "IV",
                            1 to "I"
                    )
                    .fold(Pair(StringBuilder(), n)) { (output, runnyNum), (value, numeral) ->
                        when {
                            runnyNum >= value ->
                                    output.append(numeral.repeat(runnyNum / value)) to
                                            runnyNum % value
                            else -> output to runnyNum
                        }
                    }
                    .first
                    .toString()
}

An object declaration is used to define RomanNumerals as essentially a singleton object instantiation of the class. This is sufficient, since there is no object state that needs to change with each call of the value method.

The listOf method is used to create a list of Pairs that associate an Arabic numeral with its Roman numeral.

The fold method is called on the List. Its accumulating value is initialized with a Pair, with a StringBuilder for the output and an Int to hold the value of the input number as it is calculated down.

The lambda of fold takes the accumulating value Pair as well as the Pair of each List element being iterated.

The running number is tested in a when expression. If it is greater than or equal to the Arabic value in the currently iterated Pair, then the repeat method is used to append the Roman numeral to the StringBuilder for as many times as the running number can be divided by the Arabic value with a result greater than 0. That arm of the when uses the to keyword to return the StringBuilder and the remainder of dividing the running number by the Arabic value.

If the running number is less than the Arabic value, then the when expression returns the StringBuilder and the running number as is.

When fold has iterated through all of the List elements, the first item in the accumulating value Pair is the StringBuilder. The value function returns the result of calling the toString method on the StringBuilder.

Although the value function has multiple lines, it consists only of the one expression of chained methods, so it is defined using single-expression function syntax, with the curly braces omitted and the return type inferred.

23rd Oct 2024 · Found it useful?