Various solutions for Clojure problem implementation

Here is a description of the problem:

Define a procedure that takes three numbers as arguments and returns the sum of the squares of two large numbers.

The decision is long

(defn large [x y]
(if (> x y) x y))

(defn large-3 [x y z]
(if(> (large x y) z) (large x y) z))

(defn small [x y]
(if (< x y) x y))

(defn small-3 [x y z]
(if (< (small x y) z ) (small x y) z))

(defn second-largest [x y z]
  (let [greatest (large-3 x y z)
    smallest (small-3 x y z)]
    (first (filter #(and (> greatest %) (< smallest %)) [x y z]))))

(defn square [a]
  (* a a)
)

(defn sum-of-square [x y z]
  (+ (square (large-3 x y z)) (square (second-largest x y z))))

Just wanted to know what different / concise ways to solve this problem in Clojure.

+5
source share
3 answers

(See the version sequence of the problem along with the lazy solution in the second update of this answer below.)

(defn square [n]
  (* n n))

;; generalises easily to larger numbers of arguments
(defn sum-of-larger-squares [x y z]
  (apply + (map square (take 2 (reverse (sort [x y z]))))))

;; shorter; generalises easily if you want
;; 'the sum of the squares of all numbers but n smallest'
(defn sum-of-larger-squares [x y z]
  (apply + (map square (drop 1 (sort [x y z])))))

Update:

To expand on the comments above, the first generalized version for the version is:

(defn sum-of-larger-squares [n & xs]
  (apply + (map square (take n (reverse (sort xs))))))

The second version simply summarizes the version that Arthur published meanwhile:

(defn sum-of-larger-squares [n & xs]
  (apply + (map square (drop n (sort xs)))))

, ​​ , , SO... , , ( ). "" , , , , . , , .

2:

, (, ) . , :

(use 'clojure.contrib.seq-utils) ; recently renamed to clojure.contrib.seq

(defn moving-sum-of-smaller-squares [pred n nums]
  (map first
       (reductions (fn [[current-sum [x :as current-xs]] y]
                     (if (pred y x)
                       (let [z (peek current-xs)]
                         [(+ current-sum (- (* z z)) (* y y))
                          (vec (sort-by identity pred (conj (pop current-xs) y)))])
                       [current-sum
                        current-xs]))
                   (let [initial-xs (vec (sort-by identity pred (take n nums)))
                         initial-sum (reduce + (map #(* % %) initial-xs))]
                     [initial-sum initial-xs])
                   (drop n nums))))

clojure.contrib.seq-utils ( c.c.seq) lib reductions. iterate , ( seq , , ).

:

user> (moving-sum-of-smaller-squares < 2 [9 3 2 1 0 5 3])
(90 13 5 1 1 1)

;; and to prove laziness...
user> (take 2 (moving-sum-of-smaller-squares < 2 (iterate inc 0)))
(1 1)

;; also, 'smaller' means pred-smaller here -- with
;; a different ordering, a different result is obtained
user> (take 10 (moving-sum-of-smaller-squares > 2 (iterate inc 0)))
(1 5 13 25 41 61 85 113 145 181)

, (moving-sum-of-smaller-squares pred n & nums) seq n seq , "pred-smallest" pred. pred= > n .

, , , , , , .

, ; , , seqs n , (, ).

+3
(defn foo [& xs]
  (let [big-xs (take 2 (sort-by - xs))]
    (reduce + (map * big-xs big-xs))))
+8

; why only 3? how about n

(defn sum-of-squares [& nums]  
  (reduce + (map #(* % %) (drop 1 (sort nums)))))

or if you want "the sum of the largest two numbers:

(defn sum-of-squares [& nums]  
  (reduce + (map #(* % %) (take 2 (reverse (sort nums))))))

(take 2 (reverse (sort nums))) from Michał Marczyk's answer.

+7
source

All Articles