2015-09-03 13 views
5

Napisałem poniższy kod do obliczania największego wspólnego dzielnika dwóch liczb dodatnich. Czy w kodzie są jakieś kwestie, które nie są optymalne lub wystarczająco kurejskie, a jeśli tak, to jaki byłby bardziej klasyczny sposób robienia GCD?Największy wspólny dzielnik w Clojure

(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 

Odpowiedz

5

za pomocą manipulacji sekwencja operacji liczbowych (bez przetworników) jest nieco wagi ciężkiej, a to byłaby wielka sprawa dla recur zamiast:

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

Oszczędza to trochę wysiłku/czas, że pójdzie do budynku sekwencje, które następnie są odrzucane. W tym przypadku tworzy on secuence dwóch sekwencji liczb, zamienia je w sekwencję dwóch zestawów, a następnie rozbija na pojedynczy zestaw, z którego największa wartość jest odpowiedzią.
Ogólnie, podczas definiowania zmiennych zawierających funkcje używa się defn (skrót od funkcji define) dodaje ładne rzeczy automatycznie, które bardzo pomagają w oprzyrządowaniu, np. Wyświetlając typy argumentów i takie.

+0

dziękuję. Skoro jestem nowicjuszem, czy mógłbyś wyjaśnić, jaka jest manipulacja sekwencyjna dla operacji numerycznych w moim kodzie? Byłbym wdzięczny, gdybyś mógł przedstawić mi źródło wiedzy na temat przetworników. – amirteymuri

+0

A czy algorytm zastosowałeś algorytm Euklidesa? – amirteymuri

+0

Będę edytować z więcej o sekwencjach i tak, to euclids –

0

To, co zrobiłem, to trochę krótsza i nie używa rekursji:

(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))))