2013-03-14 12 views
7

Zacząłem robić Projekt Euler za pomocą Clojure, jako pierwsze narzędzie do nauki Clojure. Mam rozwiązać pierwszą Zadanie:Czy to idiomatyczne Clojure?

Znajdź sumę wszystkich wielokrotności 3 lub 5 poniżej 1000.

ja wcześniej rozwiązać go w Pythonie:

sum(i for i in xrange(1000) if i%3==0 or i%5==0) 

To jest moja pierwsza próba Clojure:

(reduce + 
    (filter 
    (fn [x] 
     (or 
     (= 0 (mod x 3)) 
     (= 0 (mod x 5)))) 
    (range 1000))) 

Jestem naprawdę zaskoczona, jak bardzo było to pełne, ale ja Jestem pewien, że to ze względu na mój styl i nieznajomość idiomów Clojure.

Jak wyglądałaby idiomatyczna wersja tego kodu Clojure?

Odpowiedz

8

To jak to zrobiłem:

(apply + 
    (filter #(or (zero? (mod % 3)) 
       (zero? (mod % 5))) 
    (range 1000))) 

Co sprawia, że ​​moje rozwiązanie nieznacznie więcej idiomatyczne jest wykorzystanie anonimowego makro czytnika funkcja, #(...) i zero?fn

Twoje rozwiązanie jest inny, ale tak samo jak dobry!

BTW - rozwiązywanie problemów eulera to świetny sposób na naukę nowego języka - nie można uzyskać wszystkiego z książki.

Edit:

postanowiłem zapewnić inne rozwiązanie bardziej inline z twoją wersją Pythona (niezbyt ładna IMO)

(apply + 
    (for [i (range 1000) :when (or (zero? (mod i 3)) 
           (zero? (mod i 5)))] 
    i)) 
+0

Wielkie dzięki, że czyści go całkiem sporo! jaka byłaby korzyść z zastosowania metody Apply vs Reduction? – gumuz

+1

'+' ma zmienną aritę, więc uniemożliwia nam wielokrotne wykonywanie '+'. W rzeczywistości jest to równoważne użyciu 'reduce', ponieważ' + 'używa' reduce' gdy lista arg przekracza 2 (zobacz źródło '+'). W tym przykładzie jest to po prostu mój styl bardziej niż cokolwiek innego. – Kyle

+0

Jeszcze raz dziękuję, czy jest jakiś przewodnik po stylu, który na przykład zaleca sposób wyrównania argumentów? – gumuz

8

kolejną wersją:

(defn sum-of [n] 
    (reduce + (range n 1000 n))) 

(+ (sum-of 3) (sum-of 5) (- (sum-of 15))) 
+1

Śliczne.Również '(reduce + (distinct (concat (zakres 3 1000 3) (zakres 5 1000 5)))) – ToBeReplaced

0

I jak próbować rozwiązać ogólne rozwiązanie dla rzeczy Projekt Euler, więc oto moje ogólne rozwiązanie:

(defn sum-multiples [nums lim] 
    (reduce 
    + 
    (filter 
    (fn [x] 
     (some identity 
      (map #(zero? (mod x %)) nums))) 
    (range lim)))) 

a potem po prostu zadzwonić:

(sum-multiples [3 5] 1000) 
Powiązane problemy