如何使用Clojure将数字转换为罗马数字?

时间:2016-01-14 17:30:02

标签: clojure roman-numerals

我是Clojure的新手并且我的代码有问题。我正在尝试制作一个转换器。这是我的代码:

(defn romanos [numero]
  (when (and (< numero 40) (>= numero 10)) (print "X") (romanos (- numero 10)))
  (when (= numero 9) (print "IX") (romanos (- numero 9)))
  (when (>= numero 5)  (print "V") (romanos (- numero 5)))
  (when (= numero 4) (print "IV") (romanos (- numero 4)))
  (when (and (<= numero 3) (> numero 0)) (print "I") (romanos (- numero 1)))
  (when (= numero 0) (print )))

3 个答案:

答案 0 :(得分:10)

我意识到这可能是一种练习,在这种情况下,这不是你想要的答案,但是......

(clojure.pprint/cl-format nil "~@r" 123)
;= "CXXIII"

要打印到标准输出而不是返回字符串,请将nil替换为true;传入java.io.Writer实例以打印到任意流。

有关详细信息,请参阅Common Lisp HyperSpec的Formatted Output部分。

答案 1 :(得分:3)

每个when语句都按顺序运行。 1-8工作正常,但是大于8的数字会触发条件(>= numero 5)并创建第二个递归调用。

您的最终解决方案应使用cond而不是when

答案 2 :(得分:0)

我建议将所有有效罗马值的映射保留为其阿拉伯值,减去最高值,小于循环中的数字(将其罗马值添加到结果字符串):

(defn roman [n]
  (let [alphabet (sort-by val > 
                          {\I   1   \V   5   \X   10   \L   50 
                           \C   100 \D   500 \M   1000 "IV" 4
                           "IX" 9   "XL" 40  "XC" 90   "CD" 400 
                           "CM" 900})]
    (loop [res "" n n]
      (if (zero? n) res
        (let [[rom arab] (some #(when (<= (val %) n) %) alphabet)]
          (recur (str res rom) (- n arab)))))))