Skip to content

Commit 07c3256

Browse files
cawpatCallum Gibbons
and
Callum Gibbons
authored
[SCALA-649] Convert a Number to Roman Numeral in Scala (#1455)
* [SCALA-649] Convert a Number to Roman Numeral in Scala * Renamed test to UnitTest --------- Co-authored-by: Callum Gibbons <[email protected]>
1 parent 7806006 commit 07c3256

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.baeldung.scala.romannumerals
2+
3+
import scala.annotation.tailrec
4+
import scala.math.BigDecimal.int2bigDecimal
5+
6+
object NumberToRomanNumeral {
7+
8+
private val numbersToRomans = List(
9+
(1000, "M"),
10+
(900, "CM"),
11+
(500, "D"),
12+
(400, "CD"),
13+
(100, "C"),
14+
(90, "XC"),
15+
(50, "L"),
16+
(40, "XL"),
17+
(10, "X"),
18+
(9, "IX"),
19+
(5, "V"),
20+
(4, "IV"),
21+
(1, "I")
22+
)
23+
24+
def usingRecursion(num: Int): String = {
25+
numbersToRomans.find((n, _) => {
26+
num - n >= 0
27+
}) match
28+
case Some((n, r)) => r + usingRecursion(num - n)
29+
case None => ""
30+
}
31+
32+
def usingTailRecursion(num: Int): String = {
33+
@tailrec
34+
def recursiveFn(remaining: Int, acc: String): String = {
35+
numbersToRomans.find((n, _) => {
36+
remaining - n >= 0
37+
}) match
38+
case Some((n, r)) => recursiveFn(remaining - n, acc + r)
39+
case None => acc
40+
}
41+
recursiveFn(num, "")
42+
}
43+
44+
def usingFold(num: Int): String = {
45+
numbersToRomans
46+
.foldLeft((num, ""))((remainingAndAcc, numAndRoman) => {
47+
val (remaining, acc) = remainingAndAcc
48+
if (remaining == 0) remainingAndAcc
49+
else {
50+
val (n, r) = numAndRoman
51+
52+
(remaining % n, acc + r * (remaining / n))
53+
}
54+
})
55+
._2
56+
}
57+
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.baeldung.scala.romannumeral
2+
3+
import com.baeldung.scala.romannumerals.NumberToRomanNumeral
4+
import org.scalatest.matchers.should.Matchers
5+
import org.scalatest.prop.TableDrivenPropertyChecks
6+
import org.scalatest.wordspec.AnyWordSpec
7+
8+
class NumberToRomanNumeralUnitTest
9+
extends AnyWordSpec
10+
with Matchers
11+
with TableDrivenPropertyChecks {
12+
val testValuesWithResults = Table(
13+
("Number", "Roman"),
14+
(0, ""),
15+
(1, "I"),
16+
(2, "II"),
17+
(4, "IV"),
18+
(5, "V"),
19+
(6, "VI"),
20+
(9, "IX"),
21+
(10, "X"),
22+
(11, "XI"),
23+
(14, "XIV"),
24+
(15, "XV"),
25+
(17, "XVII"),
26+
(19, "XIX"),
27+
(20, "XX"),
28+
(40, "XL"),
29+
(44, "XLIV"),
30+
(49, "XLIX"),
31+
(50, "L"),
32+
(90, "XC"),
33+
(100, "C"),
34+
(400, "CD"),
35+
(500, "D"),
36+
(900, "CM"),
37+
(1000, "M"),
38+
(1949, "MCMXLIX")
39+
)
40+
41+
"Correction roman numeral should be returned for number" should {
42+
"using usingRecursion" in {
43+
forAll(testValuesWithResults)((num, roman) => {
44+
NumberToRomanNumeral.usingRecursion(num) shouldBe roman
45+
})
46+
}
47+
48+
"using usingTailRecursion" in {
49+
forAll(testValuesWithResults)((num, roman) => {
50+
NumberToRomanNumeral.usingTailRecursion(num) shouldBe roman
51+
})
52+
}
53+
54+
"using usingFold" in {
55+
forAll(testValuesWithResults)((num, roman) => {
56+
NumberToRomanNumeral.usingFold(num) shouldBe roman
57+
})
58+
}
59+
}
60+
61+
}

0 commit comments

Comments
 (0)