commit 4e626ce82569870ec779fbd4f6dfc75b45994e1a
parent 782b624edd671b2c913418b17bd365573d04017a
Author: dwrz <dwrz@dwrz.net>
Date: Fri, 8 Feb 2019 00:24:07 +0000
Add elisp/roman-numerals
Diffstat:
3 files changed, 125 insertions(+), 0 deletions(-)
diff --git a/elisp/roman-numerals/README.md b/elisp/roman-numerals/README.md
@@ -0,0 +1,49 @@
+# Roman Numerals
+
+Write a function to convert from normal numbers to Roman Numerals.
+
+The Romans were a clever bunch. They conquered most of Europe and ruled
+it for hundreds of years. They invented concrete and straight roads and
+even bikinis. One thing they never discovered though was the number
+zero. This made writing and dating extensive histories of their exploits
+slightly more challenging, but the system of numbers they came up with
+is still in use today. For example the BBC uses Roman numerals to date
+their programmes.
+
+The Romans wrote numbers using letters - I, V, X, L, C, D, M. (notice
+these letters have lots of straight lines and are hence easy to hack
+into stone tablets).
+
+```
+ 1 => I
+10 => X
+ 7 => VII
+```
+
+There is no need to be able to convert numbers larger than about 3000.
+(The Romans themselves didn't tend to go any higher)
+
+Wikipedia says: 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.
+
+To see this in practice, consider the example of 1990.
+
+In Roman numerals 1990 is MCMXC:
+
+1000=M
+900=CM
+90=XC
+
+2008 is written as MMVIII:
+
+2000=MM
+8=VIII
+
+See also: http://www.novaroma.org/via_romana/numbers.html
+## Source
+
+The Roman Numeral Kata [http://codingdojo.org/cgi-bin/index.pl?KataRomanNumerals](http://codingdojo.org/cgi-bin/index.pl?KataRomanNumerals)
+
+## Submitting Incomplete Solutions
+It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/elisp/roman-numerals/roman-numerals-test.el b/elisp/roman-numerals/roman-numerals-test.el
@@ -0,0 +1,30 @@
+;;; roman-numerals-test.el --- Tests for roman-numerals (exercism)
+
+;;; Commentary:
+
+;;; Code:
+
+(load-file "roman-numerals.el")
+
+(ert-deftest roman-numerals-test ()
+ (should (equal (to-roman 1) "I"))
+ (should (equal (to-roman 2) "II"))
+ (should (equal (to-roman 3) "III"))
+ (should (equal (to-roman 4) "IV"))
+ (should (equal (to-roman 5) "V"))
+ (should (equal (to-roman 6) "VI"))
+ (should (equal (to-roman 9) "IX"))
+ (should (equal (to-roman 27) "XXVII"))
+ (should (equal (to-roman 48) "XLVIII"))
+ (should (equal (to-roman 59) "LIX"))
+ (should (equal (to-roman 93) "XCIII"))
+ (should (equal (to-roman 141) "CXLI"))
+ (should (equal (to-roman 163) "CLXIII"))
+ (should (equal (to-roman 402) "CDII"))
+ (should (equal (to-roman 575) "DLXXV"))
+ (should (equal (to-roman 911) "CMXI"))
+ (should (equal (to-roman 1024) "MXXIV"))
+ (should (equal (to-roman 3000) "MMM")))
+
+(provide 'roman-numerals)
+;;; roman-numerals-test.el ends here
diff --git a/elisp/roman-numerals/roman-numerals.el b/elisp/roman-numerals/roman-numerals.el
@@ -0,0 +1,46 @@
+;;; roman-numerals.el --- roman-numerals Exercise (exercism)
+
+;;; Commentary:
+
+;;; Code:
+
+(provide 'roman-numerals)
+
+(defun greatest-roman-amount (n)
+ (cond ((>= n 1000) 1000)
+ ((>= n 900) 900)
+ ((>= n 500) 500)
+ ((>= n 400) 400)
+ ((>= n 100) 100)
+ ((>= n 90) 90)
+ ((>= n 50) 50)
+ ((>= n 40) 40)
+ ((>= n 10) 10)
+ ((>= n 9) 9)
+ ((>= n 5) 5)
+ ((>= n 4) 4)
+ ((>= n 1) 1)))
+
+(defun numeral-for-amount (n)
+ (cond ((= n 1000) "M")
+ ((= n 900) "CM")
+ ((= n 500) "D")
+ ((= n 400) "CD")
+ ((= n 100) "C")
+ ((= n 90) "XC")
+ ((= n 50) "L")
+ ((= n 40) "XL")
+ ((= n 10) "X")
+ ((= n 9) "IX")
+ ((= n 5) "V")
+ ((= n 4) "IV")
+ ((= n 1) "I")))
+
+(defun to-roman (n)
+"Convert whole number N to roman numeral.
+Does not handle numbers greater than 3000."
+ (cl-loop until (<= n 0)
+ concat (numeral-for-amount (greatest-roman-amount n))
+ do (setq n (- n (greatest-roman-amount n)))))
+
+;;; roman-numerals.el ends here