File tree Expand file tree Collapse file tree 2 files changed +119
-0
lines changed
scala-core-modules/scala-core-numbers/src
main/scala/com/baeldung/scala/romannumerals
test/scala/com/baeldung/scala/romannumeral Expand file tree Collapse file tree 2 files changed +119
-0
lines changed Original file line number Diff line number Diff line change
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 number Diff line number Diff line change
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
+ }
You can’t perform that action at this time.
0 commit comments