| author | Christian Urban <christian.urban@kcl.ac.uk> | 
| Tue, 08 Nov 2022 00:27:47 +0000 | |
| changeset 430 | 4029552de5fc | 
| parent 265 | 2692329287bb | 
| permissions | -rw-r--r-- | 
| 108 | 1 | // Part 1 about Roman Numerals | 
| 2 | //============================= | |
| 3 | ||
| 104 
a7ce74d89085
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: diff
changeset | 4 | abstract class RomanDigit | 
| 
a7ce74d89085
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: diff
changeset | 5 | case object I extends RomanDigit | 
| 
a7ce74d89085
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: diff
changeset | 6 | case object V extends RomanDigit | 
| 
a7ce74d89085
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: diff
changeset | 7 | case object X extends RomanDigit | 
| 
a7ce74d89085
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: diff
changeset | 8 | case object L extends RomanDigit | 
| 
a7ce74d89085
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: diff
changeset | 9 | case object C extends RomanDigit | 
| 
a7ce74d89085
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: diff
changeset | 10 | case object D extends RomanDigit | 
| 
a7ce74d89085
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: diff
changeset | 11 | case object M extends RomanDigit | 
| 105 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 12 | |
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 13 | type RomanNumeral = List[RomanDigit] | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 14 | |
| 108 | 15 | |
| 16 | // (1) First write a polymorphic function that recursively | |
| 17 | // transforms a list of options into an option of a list. | |
| 18 | // As soon as a None is inside the list, the result is None. | |
| 19 | // Otherwise produce a list of all Some's appended. | |
| 20 | ||
| 105 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 21 | def optionlist[A](xs: List[Option[A]]): Option[List[A]] = xs match {
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 22 | case Nil => Some(Nil) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 23 |   case x::xs => (x, optionlist(xs)) match {
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 24 | case (None, _) => None | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 25 | case (_, None) => None | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 26 | case (Some(y), Some(ys)) => Some(y::ys) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 27 | } | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 28 | } | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 29 | |
| 108 | 30 | optionlist(List(Some(1), Some(2), Some(3))) | 
| 31 | optionlist(List(Some(1), None, Some(3))) | |
| 32 | optionlist(List()) | |
| 33 | ||
| 34 | // (2) Write a function first a function that converts a character | |
| 35 | // into a roman digit (if possible). Then convert a string into | |
| 36 | // a roman numeral (if possible). If this is not possible, the functions | |
| 37 | // should return None. | |
| 38 | ||
| 39 | def Char2RomanDigit(c: Char): Option[RomanDigit] = c match {
 | |
| 105 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 40 | case 'I' => Some(I) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 41 | case 'V' => Some(V) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 42 | case 'X' => Some(X) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 43 | case 'L' => Some(L) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 44 | case 'C' => Some(C) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 45 | case 'D' => Some(D) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 46 | case 'M' => Some(M) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 47 | case _ => None | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 48 | } | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 49 | |
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 50 | def String2RomanNumeral(s: String) : Option[RomanNumeral] = | 
| 108 | 51 | optionlist(s.toList.map(Char2RomanDigit)) | 
| 105 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 52 | |
| 108 | 53 | // some test cases | 
| 105 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 54 | String2RomanNumeral("IIII")
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 55 | String2RomanNumeral("IV")
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 56 | String2RomanNumeral("VI")
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 57 | String2RomanNumeral("IX")
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 58 | String2RomanNumeral("MCMLXXIX")
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 59 | String2RomanNumeral("MCMXLIV") 
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 60 | String2RomanNumeral("M C M X L I V")  // None
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 61 | |
| 108 | 62 | |
| 63 | // (3) Write a recursive function RomanNumral2Int that converts a | |
| 64 | // RomanNumeral into an integer. | |
| 105 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 65 | |
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 66 | def RomanNumeral2Int(rs: RomanNumeral): Int = rs match { 
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 67 | case Nil => 0 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 68 | case M::r => 1000 + RomanNumeral2Int(r) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 69 | case C::M::r => 900 + RomanNumeral2Int(r) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 70 | case D::r => 500 + RomanNumeral2Int(r) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 71 | case C::D::r => 400 + RomanNumeral2Int(r) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 72 | case C::r => 100 + RomanNumeral2Int(r) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 73 | case X::C::r => 90 + RomanNumeral2Int(r) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 74 | case L::r => 50 + RomanNumeral2Int(r) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 75 | case X::L::r => 40 + RomanNumeral2Int(r) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 76 | case X::r => 10 + RomanNumeral2Int(r) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 77 | case I::X::r => 9 + RomanNumeral2Int(r) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 78 | case V::r => 5 + RomanNumeral2Int(r) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 79 | case I::V::r => 4 + RomanNumeral2Int(r) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 80 | case I::r => 1 + RomanNumeral2Int(r) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 81 | } | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 82 | |
| 108 | 83 | // some test cases | 
| 109 | 84 | RomanNumeral2Int(List(I,I,I,I)) // 4 (invalid roman number) | 
| 105 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 85 | RomanNumeral2Int(List(I,V)) // 4 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 86 | RomanNumeral2Int(List(V,I)) // 6 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 87 | RomanNumeral2Int(List(I,X)) // 9 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 88 | RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) // 1979 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 89 | RomanNumeral2Int(List(M,C,M,X,L,I,V)) // 1944 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 90 | |
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 91 | |
| 108 | 92 | // (4) Write a function that converts a string (containing | 
| 93 | // a roman numeral) into an integer (if possible). If not | |
| 94 | // this is not possible, the functions should return None. | |
| 95 | ||
| 105 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 96 | def String2Int(s: String): Option[Int] = | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 97 | String2RomanNumeral(s).map(RomanNumeral2Int(_)) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 98 | |
| 109 | 99 | // some test cases | 
| 100 | String2Int("IIII")      // 4 (though invalid roman numeral)  
 | |
| 105 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 101 | String2Int("IV")        // 4
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 102 | String2Int("VI")        // 6
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 103 | String2Int("IX")        // 9
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 104 | String2Int("MCMLXXIX")  // 1979
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 105 | String2Int("MCMXLIV")   // 1944
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 106 | String2Int("")          // 0
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 107 | String2Int("MDCLXI")    // 1661
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 108 | String2Int("MMMCMXCIX") // 3999
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 109 | String2Int("XLVIII")    // 48
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 110 | String2Int("MMVIII")    // 2008
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 111 | |
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 112 | String2Int("MMXI")      // 2011 
 | 
| 111 | 113 | String2Int("MIM")       // 2001
 | 
| 105 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 114 | String2Int("MCMLVI")    // 1956 
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 115 | |
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 116 | String2Int("III") 	// 3
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 117 | String2Int("XXX") 	// 30
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 118 | String2Int("CCC") 	// 300
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 119 | String2Int("MMM") 	// 3000
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 120 | String2Int("VII") 	// 7
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 121 | String2Int("LXVI") 	// 66
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 122 | String2Int("CL") 	// 150
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 123 | String2Int("MCC") 	// 1200
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 124 | String2Int("IV") 	// 4
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 125 | String2Int("IX") 	// 9
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 126 | String2Int("XC") 	// 90
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 127 | String2Int("MDCLXVI")	// 1666
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 128 | |
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 129 | |
| 265 | 130 | // error/none cases | 
| 131 | String2Int("MC?I") 
 | |
| 105 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 132 | String2Int("abc")
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 133 | |
| 109 | 134 | |
| 108 | 135 | |
| 109 | 136 | // Part 2 about Validation of Roman Numerals | 
| 137 | //=========================================== | |
| 108 | 138 | |
| 109 | 139 | def Digit2Int(r: RomanDigit) = r match {
 | 
| 140 | case I => 1 | |
| 141 | case V => 5 | |
| 142 | case X => 10 | |
| 143 | case L => 50 | |
| 144 | case C => 100 | |
| 145 | case D => 500 | |
| 146 | case M => 1000 | |
| 147 | } | |
| 105 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 148 | |
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 149 | def runsAllowed(r: RomanDigit) = r match {
 | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 150 | case I | X | C | M => true | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 151 | case V | L | D => false | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 152 | } | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 153 | |
| 109 | 154 | def subtractable(r1: RomanDigit, r2: RomanDigit) = (r1, r2)  match {
 | 
| 155 | case (I, V) | (I, X) => true | |
| 156 | case (X, L) | (X, C) => true | |
| 157 | case (C, D) | (C, M) => true | |
| 158 | case _ => false | |
| 159 | } | |
| 105 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 160 | |
| 109 | 161 | def isValidNumeral(digitList: RomanNumeral): Boolean = digitList match {
 | 
| 105 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 162 | |
| 109 | 163 | // empty list is valid | 
| 105 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 164 | case Nil => true | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 165 | |
| 109 | 166 | // no more than three runnables in succession | 
| 167 | case d1::d2::d3::d4::_ if (d1 == d2 && d1 == d3 && d1 == d4 && runsAllowed(d1)) => false | |
| 168 | ||
| 169 | // no more than one non-runnables in succession | |
| 170 | case d1::d2::_ if (d1 == d2 && !runsAllowed(d1)) => false | |
| 171 | ||
| 172 | // subtractable | |
| 173 | case d1::d2::_ if (Digit2Int(d1) < Digit2Int(d2) && !subtractable(d1, d2)) => false | |
| 174 | ||
| 175 | // followable1 | |
| 176 | case d1::d2::d3::_ if (Digit2Int(d2) < Digit2Int(d3) && subtractable(d2,d3) && | |
| 177 | Digit2Int(d1) < Digit2Int(d2) * 10) => false | |
| 178 | ||
| 179 | // followable2 | |
| 180 | case d1::d2::d3::_ if (Digit2Int(d1) < Digit2Int(d2) && subtractable(d1,d2) && | |
| 181 | Digit2Int(d1) <= Digit2Int(d3)) => false | |
| 105 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 182 | |
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 183 | // A single digit is always allowed | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 184 | case _::ds => isValidNumeral(ds) | 
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 185 | |
| 
0f9f774c7697
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
104diff
changeset | 186 | } | 
| 109 | 187 | |
| 188 | ||
| 189 | val invalids = List("IXC", "XCX", "IIII", "IIIII", "DD", "VL", "MIM", "XXCIII", "LXXIIX", "IIIIX",
 | |
| 190 | "IIXX", "ICM", "CIM", "VIV", "IVX", "MCMC", "XIIX", "IIXX") | |
| 191 | invalids.map(String2RomanNumeral(_)).flatten.map(isValidNumeral(_)) | |
| 192 | invalids.map(String2RomanNumeral(_)).flatten.map((r) => (r, isValidNumeral(r))) | |
| 193 | ||
| 194 | ||
| 195 | val valids = List("IV", "VI", "IX", "MCMLXXIX", "MCMXLIV", "", "MDCLXI",
 | |
| 196 | "MMMCMXCIX", "XLVIII", "MMVIII", "MMXI", "MCMLVI", "III", | |
| 197 | "XXX", "CCC", "MMM", "VII", "LXVI", "CL", "MCC", "XC", | |
| 198 | "MDCLXVI") | |
| 199 | valids.map(String2RomanNumeral(_)).flatten.map(isValidNumeral(_)) | |
| 200 | ||
| 201 | ||
| 202 | ||
| 203 | ||
| 204 | ||
| 205 | def Int2Roman(n: Int): RomanNumeral = n match {
 | |
| 206 | case 0 => Nil | |
| 207 | case n if (1000 <= n) => M :: Int2Roman(n - 1000) | |
| 208 | case n if (900 <= n) => C :: M :: Int2Roman(n - 900) | |
| 209 | case n if (500 <= n) => D :: Int2Roman(n - 500) | |
| 210 | case n if (400 <= n) => C :: D :: Int2Roman(n - 400) | |
| 211 | case n if (100 <= n) => C :: Int2Roman(n - 100) | |
| 212 | case n if (90 <= n) => X :: C :: Int2Roman(n - 90) | |
| 213 | case n if (50 <= n) => L :: Int2Roman(n - 50) | |
| 214 | case n if (40 <= n) => X :: L :: Int2Roman(n - 40) | |
| 215 | case n if (10 <= n) => X :: Int2Roman(n - 10) | |
| 216 | case n if (9 <= n) => I :: X :: Int2Roman(n - 9) | |
| 217 | case n if (5 <= n) => V :: Int2Roman(n - 5) | |
| 218 | case n if (4 <= n) => I :: V :: Int2Roman(n - 4) | |
| 219 | case n if (1 <= n) => I :: Int2Roman(n - 1) | |
| 220 | } | |
| 221 | ||
| 222 | ||
| 223 | Int2Roman(4) | |
| 224 | Int2Roman(6) | |
| 225 | Int2Roman(9) | |
| 226 | Int2Roman(1979) | |
| 227 | Int2Roman(1944) | |
| 228 | ||
| 229 | RomanNumeral2Int(List(I,V)) | |
| 230 | RomanNumeral2Int(List(V,I)) | |
| 231 | RomanNumeral2Int(List(I,X)) | |
| 232 | RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) | |
| 233 | RomanNumeral2Int(List(M,C,M,X,L,I,V)) | |
| 234 | ||
| 235 |