First clojure examples and Lab 1



(ns examples)

; numbers and simple expessions - just like Scheme
(def a 6)

(println a)

(println (+ 2 3))

(println [(+ 2 3)
          (< 3 5)
          (/ 10 5)
          (/ 5 2)
          (+ 1 2 3 4 5)
          (. Math sqrt 4) ; calling a java method
          (. Math pow 2 200)
          (Math/sqrt 4) ; a shorter way of calling a java method
          (Math/pow 2 200)]) 

; lists are familiar from Scheme
(def fruit '("apple" "banana" "strawberry"))

(println (nth fruit 2))

(println (cons "kiwi" fruit))

(println (first fruit))

(println (rest fruit))

; vectors are more common than lists:
(def colors ["red" "green" "blue"])

(println colors)

; cant's do 
;("apple" "banana" "strawberry") 
; without '

; define a function 
(defn average [x y] (/ (+ x y) 2))

(println (average 3 5))

(defn square [x] (* x x))

; map maps a fucntion over a sequence, returns the result as
; a sequence (that looks like a list)
(println [(map square [1 2 3 4])
          (map square '(1 2 3 4))
          (map average [1 2 3 ] [-1 -2 -3])
          (map average [1 2 3 ] '(-1 -2 -3))
])

(defn starts-a
  [string] 
  (= (.charAt string 0) \a))

(println [(filter even? '(1 2 3 4 5 6 7 8 9 0))
          (filter starts-a fruit)])

(println [(reduce + [1 2 3 4]) 
          (reduce * [1 2 3 4]) 
          (range 1 20 2)
          (reduce + (range 1 20 2))
          (min 2 3)
          (reduce min [1 2 3 4 5]) ; use "reduce" to find the minimum element in a sequence
])

; anonymous functions
(println [(map (fn [x] (* x x)) [1 2 3 4])
          (map #(* %1 %1) [1 2 3 4])
])

(println 
          (if (< 2 3) 5 7))

; recursion (a direct definition, not tail-recursive)
(defn fact [n]
  (if (<= n 0) 1
      (* n (fact (- n 1)))))

(println [ "testing factorial:" (fact 4) (fact 0) (fact 7)] )

; checking multiple conditions:
(println [
          "Checking conditions with cond: \n"

          (cond false 1 true 2)

          (cond (= 1 2) 5 (< 3 2) 6 true 7)

          (cond (= 1 2) 5 (< 3 2) 6 false 7) ; returns nil
])

;; Lab 1 problem 1:

; you are given a list of yearly incomes. Incomes are taxed based on the
; following brackets:
; 0 - 10,000 is taxed at 10%,
; 10,000 - 30,000 is taxed at 15%
; 30,000 - 80,000 is taxed at 25%
; Note that the *entire* amount is taxed according to the bracket, so
; the income is 50,000 then the tax is 7,500. 
; use map-reduce method to compute the *total* tax paid on the list of incomes.

;; Lab 1 problem 2:
;; write a reverse_list function: a function that takes a list (or a vector) and 
;; returns a list with all the same elements, but in the opposite order. 

;; Some potentially helpful functions:
(println [
         (cons 5 [6 7])
         (first [5 6 7])
         (rest [5 6 7])
         (empty? [5 6 7])
         (empty? [])
         (empty? '())
         (concat [6 7] [9 8]) 
         (list 5)
         
])

;;; CAUTION: don't use "list" as a variable name since it's a pre-defined function!!!!

;; Lab 1 problem 3:
;; write a reverse_list2 function that takes a list and returns that list
;; in reverse order *using reduce*. 


(defn factorial [num]
(loop [n num accum 1]
  (if (<= n 0)
    accum
    (recur (- n 1) (* accum n)))))

(println ["testing loop/recur factorial:" 
          (factorial 4)  
          (factorial 0)
          (factorial 7)
])

(defn every-other [param_list]
  (loop [the_list param_list keep true result '()]
    (cond
     (empty? the_list) result
     keep (recur (rest the_list) false (concat result (list (first the_list))))
     (not keep) (recur (rest the_list) true result))))

(println ["testing every-other:" 
          (every-other [1 2 3 4 5])
          (every-other [])
          (every-other [1])
])

;; another (more efficient) version that builds a vector
;; Thanks to Brian Goslinga for pointing out the efficiency differences

(defn every-other2 [param_list]
  (loop [the_list param_list keep true result []]
    (cond
     (empty? the_list) result
     keep (recur (rest the_list) false (conj result (first the_list)))
     (not keep) (recur (rest the_list) true result))))

(println ["testing every-other:" 
          (every-other2 [1 2 3 4 5])
          (every-other2 [])
          (every-other2 [1])
])

;; Lab 2 problem 1:
;; write a function that is similar to every-other but  
;; keeps even-numbered elements instead of odd-numbered ones, i.e.
;; produces [2, 4, 9] given the list [1 2 3 4 5 9].

UMM CSci 4409