author | Christian Urban <christian dot urban at kcl dot ac dot uk> |
Wed, 25 Jan 2017 14:51:09 +0000 | |
changeset 106 | fae9db0d9793 |
parent 105 | 67ce930b5935 |
child 108 | d39b8733c6ea |
permissions | -rw-r--r-- |
104
07780accd5df
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff
changeset
|
1 |
abstract class RomanDigit |
07780accd5df
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff
changeset
|
2 |
case object I extends RomanDigit |
07780accd5df
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff
changeset
|
3 |
case object V extends RomanDigit |
07780accd5df
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff
changeset
|
4 |
case object X extends RomanDigit |
07780accd5df
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff
changeset
|
5 |
case object L extends RomanDigit |
07780accd5df
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff
changeset
|
6 |
case object C extends RomanDigit |
07780accd5df
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff
changeset
|
7 |
case object D extends RomanDigit |
07780accd5df
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff
changeset
|
8 |
case object M extends RomanDigit |
105
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
9 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
10 |
type RomanNumeral = List[RomanDigit] |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
11 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
12 |
def optionlist[A](xs: List[Option[A]]): Option[List[A]] = xs match { |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
13 |
case Nil => Some(Nil) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
14 |
case x::xs => (x, optionlist(xs)) match { |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
15 |
case (None, _) => None |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
16 |
case (_, None) => None |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
17 |
case (Some(y), Some(ys)) => Some(y::ys) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
18 |
} |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
19 |
} |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
20 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
21 |
def char2romandigit(c: Char): Option[RomanDigit] = c match { |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
22 |
case 'I' => Some(I) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
23 |
case 'V' => Some(V) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
24 |
case 'X' => Some(X) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
25 |
case 'L' => Some(L) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
26 |
case 'C' => Some(C) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
27 |
case 'D' => Some(D) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
28 |
case 'M' => Some(M) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
29 |
case _ => None |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
30 |
} |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
31 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
32 |
def String2RomanNumeral(s: String) : Option[RomanNumeral] = |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
33 |
optionlist(s.toList.map(char2romandigit)) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
34 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
35 |
String2RomanNumeral("IIII") |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
36 |
String2RomanNumeral("IV") |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
37 |
String2RomanNumeral("VI") |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
38 |
String2RomanNumeral("IX") |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
39 |
String2RomanNumeral("MCMLXXIX") |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
40 |
String2RomanNumeral("MCMXLIV") |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
41 |
String2RomanNumeral("M C M X L I V") // None |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
42 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
43 |
//////////////// |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
44 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
45 |
def RomanNumeral2Int(rs: RomanNumeral): Int = rs match { |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
46 |
case Nil => 0 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
47 |
case M::r => 1000 + RomanNumeral2Int(r) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
48 |
case C::M::r => 900 + RomanNumeral2Int(r) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
49 |
case D::r => 500 + RomanNumeral2Int(r) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
50 |
case C::D::r => 400 + RomanNumeral2Int(r) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
51 |
case C::r => 100 + RomanNumeral2Int(r) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
52 |
case X::C::r => 90 + RomanNumeral2Int(r) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
53 |
case L::r => 50 + RomanNumeral2Int(r) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
54 |
case X::L::r => 40 + RomanNumeral2Int(r) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
55 |
case X::r => 10 + RomanNumeral2Int(r) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
56 |
case I::X::r => 9 + RomanNumeral2Int(r) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
57 |
case V::r => 5 + RomanNumeral2Int(r) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
58 |
case I::V::r => 4 + RomanNumeral2Int(r) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
59 |
case I::r => 1 + RomanNumeral2Int(r) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
60 |
} |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
61 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
62 |
RomanNumeral2Int(List(I,I,I,I)) // 4 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
63 |
RomanNumeral2Int(List(I,V)) // 4 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
64 |
RomanNumeral2Int(List(V,I)) // 6 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
65 |
RomanNumeral2Int(List(I,X)) // 9 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
66 |
RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) // 1979 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
67 |
RomanNumeral2Int(List(M,C,M,X,L,I,V)) // 1944 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
68 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
69 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
70 |
def String2Int(s: String): Option[Int] = |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
71 |
String2RomanNumeral(s).map(RomanNumeral2Int(_)) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
72 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
73 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
74 |
String2Int("IIII") // 4 invalid |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
75 |
String2Int("IV") // 4 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
76 |
String2Int("VI") // 6 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
77 |
String2Int("IX") // 9 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
78 |
String2Int("MCMLXXIX") // 1979 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
79 |
String2Int("MCMXLIV") // 1944 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
80 |
String2Int("") // 0 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
81 |
String2Int("MDCLXI") // 1661 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
82 |
String2Int("MMMCMXCIX") // 3999 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
83 |
String2Int("XLVIII") // 48 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
84 |
String2Int("MMVIII") // 2008 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
85 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
86 |
String2Int("MMXI") // 2011 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
87 |
String2Int("MIM") // 1999 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
88 |
String2Int("MCMLVI") // 1956 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
89 |
String2Int("XXCIII") // ?? 103 / 83 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
90 |
String2Int("LXXIIX") // ?? 80 / 78 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
91 |
String2Int("IIIIX") // ?? 12 invalid |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
92 |
String2Int("IIXX") // ?? 20 / 18 invalid |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
93 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
94 |
String2Int("III") // 3 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
95 |
String2Int("XXX") // 30 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
96 |
String2Int("CCC") // 300 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
97 |
String2Int("MMM") // 3000 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
98 |
String2Int("VII") // 7 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
99 |
String2Int("LXVI") // 66 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
100 |
String2Int("CL") // 150 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
101 |
String2Int("MCC") // 1200 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
102 |
String2Int("IV") // 4 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
103 |
String2Int("IX") // 9 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
104 |
String2Int("XC") // 90 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
105 |
String2Int("ICM") // ?? 901 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
106 |
String2Int("CIM") // ?? 899 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
107 |
String2Int("MDCLXVI") // 1666 |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
108 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
109 |
String2Int("VIV") //9, but should be written as IX |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
110 |
String2Int("IVX") // 14 invalid |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
111 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
112 |
// error cases |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
113 |
String2Int("MC?I") |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
114 |
String2Int("abc") |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
115 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
116 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
117 |
def runsAllowed(r: RomanDigit) = r match { |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
118 |
case I | X | C | M => true |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
119 |
case V | L | D => false |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
120 |
} |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
121 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
122 |
def norunsAllowed(r: RomanDigit) = !runsAllowed(r) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
123 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
124 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
125 |
def isValidNumeral(digitList: RomanNumeral): Bool = digitList match { |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
126 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
127 |
// empty list is valid |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
128 |
case Nil => true |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
129 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
130 |
// a following digit that is equal or larger is an error |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
131 |
case d1::d2::_ if (d1 <= d2) => false |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
132 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
133 |
// A single digit is always allowed |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
134 |
case _::ds => isValidNumeral(ds) |
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
135 |
|
67ce930b5935
updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
104
diff
changeset
|
136 |
} |