Last active
November 15, 2015 15:47
-
-
Save mrbuk/54d9d835a312b65a705a to your computer and use it in GitHub Desktop.
Solution for 4clojure problem 92
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
;; | |
;; first not so idiomatic approach to the problem to convert roman numerals to decimal. | |
;; | |
(fn roman-to-dec [s] | |
(let [default-f (fn [last acc] | |
(+ acc)) | |
prefixed-f (fn [prefixes] | |
(fn [last acc] | |
(if (some #(= % last) prefixes) | |
(- acc) | |
(+ acc)))) | |
rules {\M { :acc 1000 :f default-f } | |
\D { :acc 500 :f default-f } | |
\C { :acc 100 :f (prefixed-f [\M \D]) } | |
\L { :acc 50 :f default-f } | |
\X { :acc 10 :f (prefixed-f [\C \L]) } | |
\V { :acc 5 :f default-f } | |
\I { :acc 1 :f (prefixed-f [\X \V]) }}] | |
(->> (reverse s) ;; easier to process number in revered order | |
(map #(assoc (rules %) :type %)) ;; use rules to map token -> fn | |
;; calculate the value for each digit. we use reduce as each value can depend | |
;; on his successor (CM -> MC -> [ 1000 -100 ]) | |
(reductions | |
(fn [x y] | |
(let [last-type (x :type) | |
current-type (y :type) | |
acc (y :acc) | |
f (y :f) | |
result (f last-type acc)] | |
(assoc {} :result result :type current-type))) | |
;; initial value is 0 and no type | |
{:result 0 :type nil}) | |
;; extract the results only | |
(map #(:result %)) | |
;; add up the resulting numbers | |
(reduce +)))) |
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
;; | |
;; a more idiomatic solution -> http://rosettacode.org/wiki/Roman_numerals/Decode#Clojure | |
;; | |
(fn ro2ar [r] | |
(->> (reverse r) | |
(replace (zipmap "MDCLXVI" [1000 500 100 50 10 5 1])) | |
(partition-by identity) | |
(map (partial apply +)) | |
(reduce #(if (< %1 %2) (+ %1 %2) (- %1 %2))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment