From b2ea7ebefce50179f51913aae736670658190db6 Mon Sep 17 00:00:00 2001 From: Kjetil Orbekk Date: Sun, 21 Nov 2021 14:03:26 -0500 Subject: implement roman numerals --- .../emacs-lisp/roman-numerals/roman-numerals.el | 47 ++++++++++++++++++++++ exercism/emacs-lisp/run-exercises.el | 4 ++ 2 files changed, 51 insertions(+) diff --git a/exercism/emacs-lisp/roman-numerals/roman-numerals.el b/exercism/emacs-lisp/roman-numerals/roman-numerals.el index 7ee7f15..9b556fd 100644 --- a/exercism/emacs-lisp/roman-numerals/roman-numerals.el +++ b/exercism/emacs-lisp/roman-numerals/roman-numerals.el @@ -4,7 +4,54 @@ ;;; Code: +(require 'cl-macs) +(defun rn/unfold (fn x) + (let ((res (funcall fn x))) + (when (car res) + (cons (car res) (rn/unfold fn (cdr res)))))) + +(defun rn/decimal-digits (number) + "Return the decimal digits of NUMBER as a little-endian list." + (rn/unfold (lambda (x) + (when (> x 0) + (cons (% x 10) (/ x 10)))) number)) + +(defun rn/zip (l1 l2) + (when (and l1 l2) + (cons (cons (car l1) (car l2)) + (rn/zip (cdr l1) (cdr l2))))) + +(defun rn/roman-digit (number symbols) + (cl-destructuring-bind (one five ten) symbols + (cond + ((eql 0 number) '()) + ((eql 1 number) (list one)) + ((eql 2 number) (list one one)) + ((eql 3 number) (list one one one)) + ((eql 4 number) (list one five)) + ((eql 5 number) (list five)) + ((eql 6 number) (list five one)) + ((eql 7 number) (list five one one)) + ((eql 8 number) (list five one one one)) + ((eql 9 number) (list one ten)) + ((eql 10 number) (list ten))))) + +(defvar rn/roman-symbols + '(("I" "V" "X") + ("X" "L" "C") + ("C" "D" "M") + ("M" nil nil))) + +(defun to-roman (number) + (when (> number 3000) + (error 'number-too-big)) + (let* ((decimal-digits (rn/decimal-digits number)) + (roman-digits + (mapcar (lambda (digit_syms) + (rn/roman-digit (car digit_syms) (cdr digit_syms))) + (rn/zip decimal-digits rn/roman-symbols)))) + (apply 'concat (mapcan 'identity (reverse roman-digits))))) (provide 'roman-numerals) ;;; roman-numerals.el ends here diff --git a/exercism/emacs-lisp/run-exercises.el b/exercism/emacs-lisp/run-exercises.el index 983c8f8..44831a6 100644 --- a/exercism/emacs-lisp/run-exercises.el +++ b/exercism/emacs-lisp/run-exercises.el @@ -47,4 +47,8 @@ "allergy" '("gallery" "ballerina" "regally" "clergy" "largely" "leading"))) +(load-file "roman-numerals/roman-numerals.el") +(kj-display "Roman numerals" + (to-roman 1990)) + (provide 'hello) -- cgit v1.2.3