iterate with takeWhile and last

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 = {
    Iterator
      .iterate((num, 0, List[String]()))(tup =>
        tup match {
          case (num, idx, digits) if num >= ArabicNum(idx) =>
            (num - ArabicNum(idx), idx, RomanNum(idx) :: digits)
          case (num, idx, digits) =>
            (num, idx + 1, digits)
        }
      )
      .takeWhile(tup => tup._2 < 13)
      .to(Seq)
      .last match {
      case (_, _, digits) => digits.reverse.mkString
    }
  }
}

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

The iterate() method is initialized with the input Arabic number, the value 0 for the index, and a new empty List, all wrapped in a tuple. The tuple is passed to the lambda which uses a match to destructure the lambda.

The pattern matching is used to check if the number is greater than or equal to the Arabic number in the Vector at the index. If so, a new tuple is created with 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.

Otherwise, if the number is less than the the Arabic number at the index, then a new tuple is created with the number as is, the index added to by 1, and the List as is.

The takewhile() will keep calling the iterator while the index is less than 13.

After all of the values in the Arabic Vector have been checked against the number, the tuples are collected into a Seq and the last tuple is destructured by a match that reverses the List and converts it to a String with mkString, which is returned from the roman() method.

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

9th Oct 2024 · Found it useful?