-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path018 - Roman Numerals Helper.py
150 lines (130 loc) · 4.62 KB
/
018 - Roman Numerals Helper.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
"""
Create a RomanNumerals class that can convert a roman numeral to and from an integer value.
It should follow the API demonstrated in the examples below.
Multiple roman numeral values will be tested for each helper method.
Modern Roman numerals are written by expressing each digit separately starting
with the left most digit and skipping any digit with a value of zero.
In Roman numerals 1990 is rendered: 1000=M, 900=CM, 90=XC; resulting in MCMXC.
2008 is written as 2000=MM, 8=VIII; or MMVIII.
1666 uses each Roman symbol in descending order: MDCLXVI.
Input range : 1 <= n < 4000
In this kata 4 should be represented as IV, NOT as IIII (the "watchmaker's four").
Examples
RomanNumerals.to_roman(1000) # should return 'M'
RomanNumerals.from_roman('M') # should return 1000
Symbol Value
I 1
IV 4
V 5
X 10
L 50
C 100
D 500
M 1000
"""
import unittest
import string
class RomanNumerals:
def to_roman(val: int) -> string:
res = ''
if (val > 4000):
return
thausands = (val // 1000 % 10)
if thausands:
res += thausands * 'M'
hundreds = (val // 100 % 10)
if hundreds:
if (hundreds in [1, 2, 3]):
res += hundreds * 'C'
elif (hundreds == 4):
res += 'CD'
elif (hundreds == 5):
res += 'D'
elif (hundreds in [6, 7, 8]):
res += ('D' + (hundreds - 5) * 'C')
elif (hundreds == 9):
res += 'CM'
tens = (val // 10 % 10)
if tens:
if (tens in [1, 2, 3]):
res += (tens % 5) * 'X'
elif (tens == 4):
res += 'XL'
elif (tens == 5):
res += 'L'
elif (tens in [6, 7, 8]):
res += ('L' + (tens - 5) * 'X')
elif (tens == 9):
res += 'XC'
ones = (val % 10)
if ones:
if (ones in [1, 2, 3]):
res += (ones % 5) * 'I'
elif (ones == 4):
res += 'IV'
elif (ones == 5):
res += 'V'
elif (ones in [6, 7, 8]):
res += ('V' + (ones - 5) * 'I')
elif (ones == 9):
res += 'IX'
return res
def from_roman(roman_num: string) -> int:
res = 0
previous = ''
for current in roman_num:
if (current == 'M'):
if (previous == 'C'):
# CM = 900
res += 800
else:
res += 1000
elif (current == 'D'):
if (previous == 'C'):
# CD = 400
res += 300
else:
res += 500
elif (current == 'C'):
if (previous == 'X'):
# XC = 90
res += 80
else:
res += 100
elif (current == 'L'):
if (previous == 'X'):
# XL = 40
res += 30
else:
res += 50
elif (current == 'X'):
if (previous == 'I'):
# IX = 9
res += 8
else:
res += 10
elif (current == 'V'):
if (previous == 'I'):
# IV = 4
res += 3
else:
res += 5
elif (current == 'I'):
res += 1
previous = current
return res
class TestTopWords(unittest.TestCase):
def test_to_roman_sample_tests(self):
self.assertEqual(RomanNumerals.to_roman(1000), 'M', '1000 should == "M"')
self.assertEqual(RomanNumerals.to_roman(4), 'IV', '4 should == "IV"')
self.assertEqual(RomanNumerals.to_roman(1), 'I', '1 should == "I"')
self.assertEqual(RomanNumerals.to_roman(1990), 'MCMXC', '1990 should == "MCMXC"')
self.assertEqual(RomanNumerals.to_roman(2008), 'MMVIII', '2008 should == "MMVIII"')
def test_from_roman_sample_tests(self):
self.assertEqual(RomanNumerals.from_roman('I'), 1, 'I should == 1')
self.assertEqual(RomanNumerals.from_roman('XXI'), 21, 'XXI should == 21')
self.assertEqual(RomanNumerals.from_roman('IV'), 4, 'IV should == 4')
self.assertEqual(RomanNumerals.from_roman('MMVIII'), 2008, 'MMVIII should == 2008')
self.assertEqual(RomanNumerals.from_roman('MDCLXVI'), 1666, 'MDCLXVI should == 1666')
if __name__ == '__main__':
unittest.main()