Vectors recursion

Roman Numerals
Roman Numerals in Scala
object RomanNumerals {

  val ArabicNum = Vector(1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1)
  val RomanNum = Vector(
    "M",
    "CM",
    "D",
    "CD",
    "C",
    "XC",
    "L",
    "XL",
    "X",
    "IX",
    "V",
    "IV",
    "I"
  )

  def roman(num: Int): String = {
    romanRecur(num, 0, List[String]())
  }
  @scala.annotation.tailrec
  private def romanRecur(num: Int, idx: Int, digits: List[String]): String = {
    (num, idx, digits) match {
      case (_, 13, digits) => digits.reverse.mkString
      case (num, idx, digits) if num >= ArabicNum(idx) =>
        romanRecur(num - ArabicNum(idx), idx, RomanNum(idx) :: digits)
      case (num, idx, digits) =>
        romanRecur(num, idx + 1, digits)
    }
  }
}

This approach starts by defining two Vectors, one which contains the Arabic numbers and the other their corresponding Roman numerals.

The roman() method returns the result of calling the recursive method, to which it passes the input Arabic number, the value 0 for the index, 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 index.

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

Otherwise, the number is checked if it is greater than or equal to the the Arabic number in the Vector at the index. If so, the recursive method calls itself, passing in the number subtracted by the Arabic number, the index as is, and the List prepended by the Roman numeral in the Vector at that index.

If the number is less than the the Arabic number at the index, then the recursive method calls itself with the number as is, the index added to by 1, and the List as is.

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

9th Oct 2024 · Found it useful?