aboutsummaryrefslogtreecommitdiff
path: root/challenge-047/archargelod/nim/ch_1.nim
blob: 4108cc100de7e8346bee5f5e30bedca3d1c3a41f (plain)
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]