Skip to content

Instantly share code, notes, and snippets.

@Crowbrammer
Last active April 25, 2022 20:55
Show Gist options
  • Save Crowbrammer/b1ab839f1ea6ee8f30d4723938aa6e3d to your computer and use it in GitHub Desktop.
Save Crowbrammer/b1ab839f1ea6ee8f30d4723938aa6e3d to your computer and use it in GitHub Desktop.
Srasu Roman Numeral notes
(ns translate-roman-numerals.core)
;; What follows is how I understand srasu's code.
;; This is awesome. Before, I'd do a defn with a get-in. This is better.
(def numeral-values
{\I 1
\V 5
\X 10
\L 50
\C 100
\D 500
\M 1000})
(defn numeral-comparator
[n1 n2]
;; I got a firmer grasp of `compare` looking at this.
(compare (numeral-values n1)
(numeral-values n2)))
(defn translate-roman-numerals
"Convert Roman numerals to Arabic.
I.e. XCI -> 91 "
[numerals]
;; We're going to reduce over each of the numerals. At each point
;; we'll track the previous number.
;; Note, thread goes through one form. I assumed parts of the `reduce`
;; function, `[0 \M]` and `(seq numerals)` were part of the thread.
;; The Roman subtraction logic is applied by considering the previous
;; letter, so a data structure that has the previous letter's value in
;; addition to the current sum is used: `[num <previous-letter>]`.The
;; need to do this causes a `reduce whose end result is a `[num <last letter>]`.
;; Extract the num for the final answer.
(-> (reduce
;; For readability (not here but when you first pass in [0 \M]) I'd make
;; the accumulator parameter take a map destructured via `{:keys num last-numeral}`
(fn [[num last-numeral] next-numeral]
;; The subtraction principle kicks in when low roman numerals precede
;; higher roman numerals: IV, XL, XC, CD, CM. Compare gives you a fast
;; explanation of the two inputs relation, of the previous ("I") and
;; the current ("V"). When the `numeral-comparator`, which uses `compare`,
;; returns a negative, that means a low roman numeral preceded a higher
;; and thus engages subtraction logic. Must understand `compare` generally
;; to know this, which I was weak on.
[(+ num
(if (neg? (numeral-comparator last-numeral next-numeral))
;; By this point, the number was added, not subtracted. Delete the
;; unwanted add, then subtract the roman numeral's value as intended.
(* -2 (numeral-values last-numeral))
0)
(numeral-values next-numeral))
next-numeral])
[0 \M] ;; or {:num 0 :last-numeral \M}
(seq numerals))
;; Isn't it idiomatic to wrap non-keyword thread functions in parens, i.e. `(first)`?
;; If we changed the previous to return a map, `first` would become `:num`.
first))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment