Skip to content

Instantly share code, notes, and snippets.

@miner
Last active January 4, 2021 09:38
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save miner/9ff494e7cd0c9af64d03 to your computer and use it in GitHub Desktop.
Save miner/9ff494e7cd0c9af64d03 to your computer and use it in GitHub Desktop.
;; I posted an earlier version on my blog:
;; http://fnclojure.wordpress.com/2012/08/06/roman-numerals-in-clojure/
;; This version is faster and more readable.
(defn range-down
"Returns a seq of integers from HIGH (exclusive) down to LOW (inclusive).
LOW defaults to 0. STEP is a positve decrement, defaults to 1. Like
`(reverse (range low high step))' but a bit faster."
([high] (range (dec high) -1 -1))
([high low] (range (dec high) (dec low) -1))
([high low step]
;; calculate nearest multiple of step + offset using mod
(let [h (dec high)
hi (- h (mod (- h low) step))]
(range hi (dec low) (- step)))))
(defn roman-lookup [c pow10]
(nth
(case c
\1 ["I" "X" "C" "M"]
\2 ["II" "XX" "CC" "MM"]
\3 ["III" "XXX" "CCC" "MMM"]
\4 ["IV" "XL" "CD"]
\5 ["V" "L" "D"]
\6 ["VI" "LX" "DC"]
\7 ["VII" "LXX" "DCC"]
\8 ["VIII" "LXXX" "DCCC"]
\9 ["IX" "XC" "CM"]
\0 ["" "" "" ""])
pow10))
(defn roman-numeral [n]
{:pre [(< 0 n 4000)]}
(let [digits (seq (str n))]
(apply str (map roman-lookup digits (range-down (count digits))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment