(:use [clojure.contrib.generic.math-functions :only (sqr)]))
(defn leaf? [t]
(not (sequential? t)))
(defn square-tree [t]
(map (fn [sub-t]
(if (leaf? sub-t) (* sub-t sub-t)
(defn square-tree-look-ma-no-map [t]
(if (empty? t) nil
(if (leaf? (first t))
(cons (* (first t) (first t)) (square-tree-look-ma-no-map (rest t)))
; Firstly I wrote (list) instead of (cons). Had to scracth my head about that.
(cons (square-tree-look-ma-no-map (first t)) (square-tree-look-ma-no-map (rest t))))))
(def *test-list* [1 [2 [3 4] 5] [6 7]])
(def *test-result* [1 [4 [9 16] 25] [36 49]])
(is (= (square-tree *test-list*) *test-result*))
(is (= (square-tree-look-ma-no-map *test-list*) *test-result*)))
(defn tree-map [f t]
(map (fn [sub-t]
(if (leaf? sub-t) (f sub-t)
(tree-map f sub-t)))
(defn square-tree-with-map [t]
(tree-map sqr t))
(is (= (square-tree-with-map *test-list*) *test-result*)))
We need to fill the function definition for the function which will map over the tail of the list.
(defn subsets [xs]
(if (empty? xs)
; We can't use  instead of [] as (map f ) exexutes f zero times while (map f []) executes (f ) once
; 1. For the xs with length = 1, remaining will hold a set containing an empty set - []
; which is a starting point for the accumulation.
(let [remaining (subsets (rest xs))]
; 2. Then, during each step the 'remaining' set of sets will be joined with another set.
; The other set is the same 'remaining' set of sets where each inner set is prefixed
; by a value from the original set 'xs'.
; Each recursive call to the (subsets) shrinks the original 'xs' set by one, so that
; the prefix is the n-th element of the 'xs' where 'n' is the nesting of the recursion.
(map (fn [x]
(if (empty? x)
; We don't want empty lists (acquired at the beginning of the (subsets)) messing up our results
(list (first xs))
; here we join a value from the original set and a list of subsets accumulated so far
(cons (first xs) x)))
(is (= (subsets [1 2 3])
[   [2 3]  [1 3] [1 2] [1 2 3]])))