Last active
April 25, 2022 20:55
-
-
Save Crowbrammer/b1ab839f1ea6ee8f30d4723938aa6e3d to your computer and use it in GitHub Desktop.
Srasu Roman Numeral notes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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