Map recursion

Roman Numerals
Roman Numerals in Scala
object RomanNumerals {
  val ArabicToRoman = Map(
    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"
  )

  def roman(num: Int): String = romanRecur(num, List[String]())

  @scala.annotation.tailrec
  def romanRecur(num: Int, digits: List[String]): String =
    (num, digits) match {
      case (0, digits) => digits.reverse.mkString
      case (num, digits) => {
        val digit = ArabicToRoman.keys.filter(_ <= num).max
        romanRecur(num - digit, ArabicToRoman(digit) :: digits)
      }
    }
}

This approach starts by defining a Map which relates the Arabic numbers to their corresponding Roman numerals.

The roman() method returns the result of calling the recursive method, to which it passes the input Arabic number and a new empty List.

The recursive method is annotated with the @tailrec annotation to verify that the method can be compiled with tail call optimization.

A tail call is a particular form of recursion where the last call in the method is a call to the same method and nothing else.

In other words, if the last call in recurMe() is recurMe(arg1, arg2) + 1, the + 1 makes the recursion non-tail recursive.

If the last call in recurMe() is recurMe(arg1, arg2, acc + 1), then the recursion is a tail call, because only the method is being called with no other operation being peformed on it.

The match is used to check the number.

The pattern matching checks if the number has calculated down to 0. If so, the List is reversed and converted to a String with mkString, which is returned from the recursive method.

Otherwise, the max Arabic number which is less than or equal to the number is filtered from the Map. The recursive method calls itself, passing in the number subtracted by the filtered number, and the List prepended by the Roman numeral associated with the Arabic number in the Map.

Note that the operations on the values create new values instead of mutating them, thus supporting immutability.

8th May 2024 · Found it useful?