Skip to content

Commit 4973a04

Browse files
add roman numerals (#39)
* exercise boilerplate * generate test cases * example solution to pass tests
1 parent c2b9dcf commit 4973a04

16 files changed

Lines changed: 1919 additions & 0 deletions

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,14 @@
157157
"prerequisites": [],
158158
"difficulty": 2
159159
},
160+
{
161+
"slug": "roman-numerals",
162+
"name": "Roman Numerals",
163+
"uuid": "11463a13-d10e-4a06-9063-977266ad706e",
164+
"practices": [],
165+
"prerequisites": [],
166+
"difficulty": 2
167+
},
160168
{
161169
"slug": "rotational-cipher",
162170
"name": "Rotational Cipher",
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Introduction
2+
3+
Your task is to convert a number from Arabic numerals to Roman numerals.
4+
5+
For this exercise, we are only concerned about traditional Roman numerals, in which the largest number is MMMCMXCIX (or 3,999).
6+
7+
~~~~exercism/note
8+
There are lots of different ways to convert between Arabic and Roman numerals.
9+
We recommend taking a naive approach first to familiarise yourself with the concept of Roman numerals and then search for more efficient methods.
10+
11+
Make sure to check out our Deep Dive video at the end to explore the different approaches you can take!
12+
~~~~
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Description
2+
3+
Today, most people in the world use Arabic numerals (0–9).
4+
But if you travelled back two thousand years, you'd find that most Europeans were using Roman numerals instead.
5+
6+
To write a Roman numeral we use the following Latin letters, each of which has a value:
7+
8+
| M | D | C | L | X | V | I |
9+
| ---- | --- | --- | --- | --- | --- | --- |
10+
| 1000 | 500 | 100 | 50 | 10 | 5 | 1 |
11+
12+
A Roman numeral is a sequence of these letters, and its value is the sum of the letters' values.
13+
For example, `XVIII` has the value 18 (`10 + 5 + 1 + 1 + 1 = 18`).
14+
15+
There's one rule that makes things trickier though, and that's that **the same letter cannot be used more than three times in succession**.
16+
That means that we can't express numbers such as 4 with the seemingly natural `IIII`.
17+
Instead, for those numbers, we use a subtraction method between two letters.
18+
So we think of `4` not as `1 + 1 + 1 + 1` but instead as `5 - 1`.
19+
And slightly confusingly to our modern thinking, we write the smaller number first.
20+
This applies only in the following cases: 4 (`IV`), 9 (`IX`), 40 (`XL`), 90 (`XC`), 400 (`CD`) and 900 (`CM`).
21+
22+
Order matters in Roman numerals!
23+
Letters (and the special compounds above) must be ordered by decreasing value from left to right.
24+
25+
Here are some examples:
26+
27+
```text
28+
105 => CV
29+
---- => --
30+
100 => C
31+
+ 5 => V
32+
```
33+
34+
```text
35+
106 => CVI
36+
---- => --
37+
100 => C
38+
+ 5 => V
39+
+ 1 => I
40+
```
41+
42+
```text
43+
104 => CIV
44+
---- => ---
45+
100 => C
46+
+ 4 => IV
47+
```
48+
49+
And a final more complex example:
50+
51+
```text
52+
1996 => MCMXCVI
53+
----- => -------
54+
1000 => M
55+
+ 900 => CM
56+
+ 90 => XC
57+
+ 5 => V
58+
+ 1 => I
59+
```
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
**/*.res.js
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
let roman = n => {
2+
let rec aux = (s, remainder) => {
3+
switch remainder {
4+
| r if r >= 1000 => aux(s ++ "M", r - 1000)
5+
| r if r >= 900 => aux(s ++ "CM", r - 900)
6+
| r if r >= 500 => aux(s ++ "D", r - 500)
7+
| r if r >= 400 => aux(s ++ "CD", r - 400)
8+
| r if r >= 100 => aux(s ++ "C", r - 100)
9+
| r if r >= 90 => aux(s ++ "XC", r - 90)
10+
| r if r >= 50 => aux(s ++ "L", r - 50)
11+
| r if r >= 40 => aux(s ++ "XL", r - 40)
12+
| r if r >= 10 => aux(s ++ "X", r - 10)
13+
| r if r >= 9 => aux(s ++ "IX", r - 9)
14+
| r if r >= 5 => aux(s ++ "V", r - 5)
15+
| r if r >= 4 => aux(s ++ "IV", r - 4)
16+
| r if r >= 1 => aux(s ++ "I", r - 1)
17+
| _ => s
18+
}
19+
}
20+
aux("", n)
21+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
let roman: int => string
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"authors": [
3+
"therealowenrees"
4+
],
5+
"files": {
6+
"solution": [
7+
"src/RomanNumerals.res",
8+
"src/RomanNumerals.resi"
9+
],
10+
"test": [
11+
"tests/RomanNumerals_test.res"
12+
],
13+
"example": [
14+
".meta/RomanNumerals.res",
15+
".meta/RomanNumerals.resi"
16+
]
17+
},
18+
"blurb": "Convert modern Arabic numbers into Roman numerals.",
19+
"source": "The Roman Numeral Kata",
20+
"source_url": "https://codingdojo.org/kata/RomanNumerals/"
21+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[19828a3a-fbf7-4661-8ddd-cbaeee0e2178]
13+
description = "1 is I"
14+
15+
[f088f064-2d35-4476-9a41-f576da3f7b03]
16+
description = "2 is II"
17+
18+
[b374a79c-3bea-43e6-8db8-1286f79c7106]
19+
description = "3 is III"
20+
21+
[05a0a1d4-a140-4db1-82e8-fcc21fdb49bb]
22+
description = "4 is IV"
23+
24+
[57c0f9ad-5024-46ab-975d-de18c430b290]
25+
description = "5 is V"
26+
27+
[20a2b47f-e57f-4797-a541-0b3825d7f249]
28+
description = "6 is VI"
29+
30+
[ff3fb08c-4917-4aab-9f4e-d663491d083d]
31+
description = "9 is IX"
32+
33+
[6d1d82d5-bf3e-48af-9139-87d7165ed509]
34+
description = "16 is XVI"
35+
36+
[2bda64ca-7d28-4c56-b08d-16ce65716cf6]
37+
description = "27 is XXVII"
38+
39+
[a1f812ef-84da-4e02-b4f0-89c907d0962c]
40+
description = "48 is XLVIII"
41+
42+
[607ead62-23d6-4c11-a396-ef821e2e5f75]
43+
description = "49 is XLIX"
44+
45+
[d5b283d4-455d-4e68-aacf-add6c4b51915]
46+
description = "59 is LIX"
47+
48+
[4465ffd5-34dc-44f3-ada5-56f5007b6dad]
49+
description = "66 is LXVI"
50+
51+
[46b46e5b-24da-4180-bfe2-2ef30b39d0d0]
52+
description = "93 is XCIII"
53+
54+
[30494be1-9afb-4f84-9d71-db9df18b55e3]
55+
description = "141 is CXLI"
56+
57+
[267f0207-3c55-459a-b81d-67cec7a46ed9]
58+
description = "163 is CLXIII"
59+
60+
[902ad132-0b4d-40e3-8597-ba5ed611dd8d]
61+
description = "166 is CLXVI"
62+
63+
[cdb06885-4485-4d71-8bfb-c9d0f496b404]
64+
description = "402 is CDII"
65+
66+
[6b71841d-13b2-46b4-ba97-dec28133ea80]
67+
description = "575 is DLXXV"
68+
69+
[dacb84b9-ea1c-4a61-acbb-ce6b36674906]
70+
description = "666 is DCLXVI"
71+
72+
[432de891-7fd6-4748-a7f6-156082eeca2f]
73+
description = "911 is CMXI"
74+
75+
[e6de6d24-f668-41c0-88d7-889c0254d173]
76+
description = "1024 is MXXIV"
77+
78+
[efbe1d6a-9f98-4eb5-82bc-72753e3ac328]
79+
description = "1666 is MDCLXVI"
80+
81+
[bb550038-d4eb-4be2-a9ce-f21961ac3bc6]
82+
description = "3000 is MMM"
83+
84+
[3bc4b41c-c2e6-49d9-9142-420691504336]
85+
description = "3001 is MMMI"
86+
87+
[2f89cad7-73f6-4d1b-857b-0ef531f68b7e]
88+
description = "3888 is MMMDCCCLXXXVIII"
89+
90+
[4e18e96b-5fbb-43df-a91b-9cb511fe0856]
91+
description = "3999 is MMMCMXCIX"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Exercism
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)