Trying to write a recursive function that adds successive pairs in a vector.
[1 2 3 4] => [3 5 7]
Pretty much stuck and this is what I h
Here is another possible solution:
(def tmp [1 2 3 4])
(map + tmp (rest tmp))
Partition takes an extra argument specifying how far to step forward between each partition.
(map #(apply + %) (partition 2 1 [1 2 3 4 5]))
=>
(3 5 7 9)
You are asking for a recursive function, and even though in most cases set and list functions are preferable above crafting your own recursive function, this is not always possible. This problem is also very easy to write recursively in a idiomatic functional way, using an accumulator
The idea is you start with an empty accumulator, and build your result step by step. The accumulator (acc in this code snippet) will hold the answer in the end.
(defn add-pairs [v1]
(loop [the-list v1 acc []]
(if (next the-list) ;; checks wether there's more than 1 left in the-list
(recur (rest the-list )
(conj acc (+ (first the-list) (second the-list))))
acc)))
What happens here? You pass vector [1 2 3 4]
to v1
.
Then the loop starts and in it , two variables are initialized :
the-list <- [1 2 3 4]
acc []
Simply enough the sum of the first two elements (+ (first the-list) (second the-list)
are added to the accumulator. Then with recur
the loop is called again passing the rest of the list (rest the-list)
and the accumulator, now holding 3 (being the sum of the two first elements). The new vaues are :
the-list <- [2 3 4]
acc [3]
next steps :
the-list <- [3 4]
acc [3 5]
the-list <- [4]
acc [3 5 7]
Then the if condition no longer holds and the else clause is returned (conveniently being the accumulator, now holding the solution).
General idea
You start out with an empty accumulator and your input set. Each step, the accumulator builds up. In most cases, the input set is getting smaller each step too. Then some if-condition is met and the accumulator returns.
Also very classic in this particular problem is that the input set is loosing its first element each step. (rest ) is very practical here ( cdr in most other lisps).
general form
The loop/recur form in clojure is very nice, but in a lot other languages, this syntax is lacking. A very classical solution is to have two functions : one recursive that does the looping, and one with the same name, but other arity that does the initialization of the accumulator. Simpler in code than it is to explain, so here it is in some made up java-like syntax :
function add-pairs(v1 acc) {
if (cond)
//do stuff to v1 and acc
add-pairs(v1 acc)
else
return acc }
function add-pairs(v1) {
return add-pairs(v1,[])
}
var result = add-pairs([42 666 1447])