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
|
#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
import std/[strutils, parseutils]
type RomanDigit = enum
I = 1
V = 5
X = 10
L = 50
C = 100
D = 500
M = 1000
const
Squish = {
"VIIII": "IX",
"LXXXX": "XC",
"DCCCC": "CM",
"IIII": "IV",
"XXXX": "XL",
"CCCC": "CD",
}
const RomanDescending = [M, D, C, L, X, V, I]
proc toRoman(dec: int): string =
var dec = dec
while dec > 0:
for roman in RomanDescending:
if dec >= roman.ord:
dec -= roman.ord
result &= $roman
break
for (sub, by) in Squish:
result = result.replace(sub, by)
proc toDec(roman: string): int =
var prev = M
for c in roman:
let r = parseEnum[RomanDigit]($c)
result += r.ord
if prev < r:
result -= prev.ord * 2
prev = r
proc romanCalculator(input: string): string =
let tmp = input.splitWhitespace()
assert tmp.len == 3
let (arg1, op, arg2) = (tmp[0], tmp[1], tmp[2])
toRoman(
case op
of "+": toDec(arg1) + toDec(arg2)
of "-": toDec(arg1) - toDec(arg2)
of "*": toDec(arg1) * toDec(arg2)
else:
raiseAssert("Invalid expression")
)
when isMainModule:
import std/unittest
const
Test = [
"XXXVI + X",
"DIV - X",
"VII * X",
]
Expected = [
"XLVI",
"CDXCIV",
"LXX",
]
suite "Show multiple arrays content":
test "Addition":
check romanCalculator(Test[0]) == Expected[0]
test "Subtraction":
check romanCalculator(Test[1]) == Expected[1]
test "Multiplication":
check romanCalculator(Test[2]) == Expected[2]
|