Clojure中的最大公约数

5

我已经编写了下面的代码来计算两个正整数的最大公约数。在代码中是否有一些不够优化或者Clojurian,如果有的话,更好的Clojurian方法是什么?

(def gcd (fn [a b] (->> (map (fn [x]
                                 (filter #(zero? (mod x %)) (range 1 (inc x))))
                        [a b])
                        (map set)
                        (apply clojure.set/intersection)
                        (apply max))))

(gcd 1023 858)` => 33
4个回答

9

在没有使用transducers的情况下,使用序列操作进行数字操作有点笨重,这是一个很好的使用 recur 的案例:

user> (defn gcd [a b]
        (if (zero? b)
          a
          (recur b (mod a b))))
#'user/gcd
user> (gcd 1023 858)
33

这样可以节省构建随后被丢弃的序列所需的时间和精力。在这种情况下,它创建了两个数字序列的序列,将其转换为两个集合的序列,然后将其压缩成单个集合,其中最大的值就是答案。
此外,通常在定义包含函数的变量时使用defn(define function的简称),它会自动添加一些很好的东西,对工具非常有帮助,例如显示参数类型等。


谢谢。由于我是新手,您能否解释一下我的代码中的数字操作序列操作是什么?如果您能介绍一个学习更多有关传输器的来源,我将不胜感激。 - user4813927
你使用的算法是欧几里得算法吗? - user4813927
我会编辑更多关于序列的内容,是的,那就是欧几里得。 - Arthur Ulfeldt
你是指在将它们转换为集合之前,第一组和第二组数字序列是由(filter)(range)创建的吗? - user4813927

5

还应该提及“只使用Java”的方法:

(defn gcd [a b]
  (.gcd (biginteger a) (biginteger b)))

1
这是我的做法,它更加简短,而且不使用递归:
(defn gcd
  [a b]
  (last
    (filter
      #(and (zero? (mod b %)) (zero? (mod a %)))
      (range 1 (inc (min a b)))
      )
    )
  )

-1
(loop [a (map #(Integer/parseInt %) (clojure.string/split (read-line) #" "))]
    (cond
        (reduce > a) (recur (list (reduce - a) (last a)))
        (reduce < a) (recur (list (- (reduce - a)) (first a)))
        (reduce = a) (println (first a))))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接