Commits

tednaleid committed da027a8

initial commit

Comments (0)

Files changed (7)

+/pom.xml
+*jar
+/lib
+/classes
+/native
+/.lein-failures
+/checkouts
+/.lein-deps-sum
+syntax: glob
+*.un~
+lib/*.jar
+.lein-deps-sum
+# four-clojure #
+
+I'm working through the 4clojure (http://4clojure.com) problem set, here are the answers that I've come up with so far
+
+## License ##
+
+Copyright (C) 2011 Ted Naleid
+
+Distributed under the Eclipse Public License, the same as Clojure.
+(defproject four-clojure "1.0.0-SNAPSHOT"
+  :description "Solutions figured out so far for 4clojure.com problems"
+  :dependencies [[org.clojure/clojure "1.3.0"]])

src/four_clojure/answered.clj

+(ns four-clojure.core)
+
+; http://www.4clojure.com/problem/5
+; Lists: conj
+; When operating on a list, the conj function will return a new list with one or more items "added" to the front.
+(= '(1 2 3 4) (conj '(2 3 4) 1))
+
+
+; http://www.4clojure.com/problem/6
+; Intro to Vectors
+; Vectors can be constructed several ways. You can compare them with lists.
+(= [:a :b :c] (list :a :b :c) (vec '(:a :b :c)) (vector :a :b :c))
+
+; http://www.4clojure.com/problem/7
+; Vectors: conj
+; When operating on a Vector, the conj function will return a new vector with one or more items "added" to the end.
+(= [1 2 3 4] (conj [1 2] 3 4))
+
+
+; http://www.4clojure.com/problem/8
+; Intro to Sets
+(= #{:a :b :c :d} (clojure.set/union #{:a :b :c} #{:b :c :d}))
+
+; http://www.4clojure.com/problem/9
+; Sets: conj
+(= #{1 2 3 4} (conj #{1 4 3} 2))
+
+; http://www.4clojure.com/problem/10
+; Intro to Maps
+; Maps store key-value pairs. Both maps and keywords can be used as lookup functions. Commas can be used to make maps more readable, but they are not required.
+(= 20 (:b {:a 10, :b 20, :c 30}))
+
+
+; http://www.4clojure.com/problem/11
+; Maps: conj
+; When operating on a map, the conj function returns a new map with one or more key-value pairs "added".
+(= {:a 1, :b 2, :c 3} (conj {:a 1} {:b 2} [:c 3]))
+
+; http://www.4clojure.com/problem/12
+; Intro to Sequences
+; All Clojure collections support sequencing. You can operate on sequences with functions like first, second, and last.
+
+(= 3 (first '(3 2 1)))
+(= 3 (second [2 3 4]))
+(= 3 (last (list 1 2 3)))
+
+; http://www.4clojure.com/problem/13
+; Sequences: rest
+; The rest function will return all the items of a sequence except the first.
+
+(= [20 30 40] (rest [10 20 30 40]))
+
+
+; http://www.4clojure.com/problem/14
+; Intro to Functions
+; Clojure has many different ways to create functions.
+(= 8 ((fn add-five [x] (+ x 5)) 3))
+(= 8 ((fn [x] (+ x 5)) 3))
+(= 8 (#(+ % 5) 3))
+(= 8 ((partial + 5) 3))
+
+
+; http://www.4clojure.com/problem/15
+; Double Down
+; Write a function which doubles a number
+(= (* 2 2) 4)
+(= (* 2 11) 22)
+
+; http://www.4clojure.com/problem/16
+; Hello World
+; Write a function which returns a personalized greeting.
+(= (#(str "Hello, " % "!") "Dave") "Hello, Dave!")
+
+; http://www.4clojure.com/problem/17
+; Sequences: map
+; The map function takes two arguments: a function (f) and a sequence (s). Map returns a new sequence consisting of the result of applying f to each item of s. Do not confuse the map function with the map data structure.
+(= [6 7 8] (map #(+ % 5) '(1 2 3)))
+
+; http://www.4clojure.com/problem/18
+; Sequences: filter
+; The filter function takes two arguments: a predicate function (f) and a sequence (s). Filter returns a new sequence consisting of all the items of s for which (f item) returns true.
+(= [6 7] (filter #(> % 5) '(3 4 5 6 7)))
+
+
+; http://www.4clojure.com/problem/35
+; Local bindings
+; Clojure lets you give local names to values using the special let-form.
+(= 7 (let [x 5] (+ 2 x)))
+
+; http://www.4clojure.com/problem/36
+; Let it Be
+; Can you bind x, y and z so that these are all true?
+
+(= 10 (let [x 7 y 3 z 1] (+ x y)))
+(= 4 (let [x 7 y 3 z 1] (+ y z)))
+(= 1 (let [x 7 y 3 z 1] z))
+
+
+; http://www.4clojure.com/problem/37
+; Regular Expressions
+; Regex patterns are supported with a special reader macro.
+(= "ABC" (apply str (re-seq #"[A-Z]+" "bA1B3Ce ")))
+
+; http://www.4clojure.com/problem/64
+; Intro to Reduce
+; Reduce takes a 2 argument function and an optional starting value. It then applies the function to the first 2 items in the sequence (or the starting value and the first element of the sequence). In the next iteration the function will be called on the previous return value and the next item from the sequence, thus reducing the entire collection to one value. Don't worry, it's not as complicated as it sounds.
+(= 15 (reduce + [1 2 3 4 5]))
+(=  0 (reduce + []))
+(=  6 (reduce + 1 [2 3]))
+
+; http://www.4clojure.com/problem/57
+; Simple Recursion
+; A recursive function is a function which calls itself. This is one of the fundamental techniques used in functional programming.
+(= [5 4 3 2 1] ((fn foo [x] (when (> x 0) (conj (foo (dec x)) x))) 5))
+
+; http://www.4clojure.com/problem/71
+; Rearranging Code: ->
+; The -> macro threads an expression x through a variable number of forms. First, x is inserted as the second item in the first form, making a list of it if it is not a list already. Then the first form is inserted as the second item in the second form, making a list of that form if necessary. This process continues for all the forms. Using -> can sometimes make your code more readable.
+(= (last (sort (rest (reverse [2 5 4 1 3 6]))))
+   (-> [2 5 4 1 3 6] reverse rest sort last)
+   5)
+
+; http://www.4clojure.com/problem/68
+; Recurring Theme
+; Clojure only has one non-stack-consuming looping construct: recur. Either a function or a loop can be used as the recursion point. Either way, recur rebinds the bindings of the recursion point to the values it is passed. Recur must be called from the tail-position, and calling it elsewhere will result in an error.
+(= [7 6 5 4 3]
+  (loop [x 5
+         result []]
+    (if (> x 0)
+      (recur (dec x) (conj result (+ 2 x)))
+      result)))
+
+; http://www.4clojure.com/problem/72
+; Rearranging Code: ->>
+; The ->> macro threads an expression x through a variable number of forms. First, x is inserted as the last item in the first form, making a list of it if it is not a list already. Then the first form is inserted as the last item in the second form, making a list of that form if necessary. This process continues for all the forms. Using ->> can sometimes make your code more readable.
+(= (reduce + (map inc (take 3 (drop 2 [2 5 4 1 3 6]))))
+   (->> [2 5 4 1 3 6] (drop 2) (take 3) (map inc) (reduce +))
+   11)
+
+; http://www.4clojure.com/problem/134
+; A nil key
+; Write a function which, given a key and map, returns true iff the map contains an entry with that key and its value is nil.
+(defn nil-key? [x m]
+  (and (contains? m x) (nil? (get m x))))
+
+(true?  (nil-key? :a {:a nil :b 2}))
+	
+(false? (nil-key? :b {:a nil :b 2}))
+	
+(false? (nil-key? :c {:a nil :b 2}))
+
+; http://www.4clojure.com/problem/145
+; For the win
+; Clojure's for macro is a tremendously versatile mechanism for producing a sequence based on some other sequence(s). It can take some time to understand how to use it properly, but that investment will be paid back with clear, concise sequence-wrangling later. With that in mind, read over these for expressions and try to see how each of them produces the same result.
+(defn for-the-win [] (range 1 40 4))
+(= (for-the-win) (for [x (range 40)
+            :when (= 1 (rem x 4))]
+        x))
+(= (range 1 40 4) (for [x (iterate #(+ 4 %) 0)
+            :let [z (inc x)]
+            :while (< z 40)]
+        z))
+(= (range 1 40 4) (for [[x y] (partition 2 (range 20))]
+        (+ x y)))
+
+; http://www.4clojure.com/problem/19
+; Last Element
+; Write a function which returns the last element in a sequence.
+; restriction: last
+
+(defn last-element [s] 
+  (reduce (fn [x y] y) 
+  s))
+(= (last-element [1 2 3 4 5]) 5)
+(= (last-element '(5 4 3)) 3)
+(= (last-element ["b" "c" "d"]) "d")
+
+; http://www.4clojure.com/problem/20
+; Penultimate Element
+; Write a function which returns the second to last element from a sequence.
+(defn penultimate [s]
+  ((comp first rest reverse) s))
+(= (penultimate (list 1 2 3 4 5)) 4)
+(= (penultimate ["a" "b" "c"]) "b")
+(= (penultimate [[1 2] [3 4]]) [1 2])
+
+; http://www.4clojure.com/problem/21
+; Nth Element
+; Write a function which returns the Nth element from a sequence
+; restriction: nth
+(defn my-nth [a x] (if (= 0 x) (first a) (my-nth (rest a) (- x 1))))
+; or 
+; #(first (drop %2 %))
+
+(= (my-nth '(4 5 6 7) 2) 6)
+(= (my-nth [:a :b :c] 0) :a)
+(= (my-nth [1 2 3 4] 1) 2)
+(= (my-nth '([1 2] [3 4] [5 6]) 2) [5 6])
+
+; http://www.4clojure.com/problem/22
+; Count a Sequence
+; Write a function which returns the total number of elements in a sequence
+; restriction: count
+(defn my-count [s] (reduce (fn [i x] (+ 1 i)) 0 s))
+
+(= (my-count '(1 2 3 3 1)) 5)
+(= (my-count "Hello World") 11)
+(= (my-count [[1 2] [3 4] [5 6]]) 3)
+(= (my-count '(13)) 1)
+(= (my-count '(:a :b :c)) 3)
+
+; http://www.4clojure.com/problem/24
+; Sum It All Up
+; Write a function which returns the sum of a sequence of numbers
+(defn sum [s] (reduce + s))
+
+(= (sum [1 2 3]) 6)
+(= (sum (list 0 -2 5 5)) 8)
+(= (sum #{4 2 1}) 7)
+(= (sum '(0 0 -1)) -1)
+(= (sum '(1 10 3)) 14)
+
+
+; http://www.4clojure.com/problem/25
+; Find the odd numbers
+; Write a function which returns only the odd numbers from a sequence
+(defn only-odds [s] (filter odd? s))
+
+(= (only-odds #{1 2 3 4 5}) '(1 3 5))
+(= (only-odds [4 2 1 6]) '(1))
+(= (only-odds [2 2 4 6]) '())
+(= (only-odds [1 1 1 3]) '(1 1 1 3))
+
+; http://www.4clojure.com/problem/23
+; Reverse a Sequence
+; Write a funciton which reverses a sequence
+; restriction: rseq, reverse
+(defn my-reverse [s]
+    (reduce conj '() s)
+  )
+; or
+; into ()
+(= (my-reverse [1 2 3 4 5]) [5 4 3 2 1])
+(= (my-reverse (sorted-set 5 7 2 7)) '(7 5 2))
+(= (my-reverse [[1 2][3 4][5 6]]) [[5 6][3 4][1 2]])
+
+
+; http://www.4clojure.com/problem/27
+; Palindrome Detector
+; Write a function which returns true if the given sequence is a palindrome.
+; Hint: "racecar" does not equal '(\r \a \c \e \c \a \r)
+(defn palindrome? [s] (= (seq s) (reverse s)))
+
+(false? (palindrome? '(1 2 3 4 5)))
+(true? (palindrome? "racecar"))
+(true? (palindrome? [:foo :bar :foo]))
+(true? (palindrome? '(1 1 3 3 1 1)))
+(false? (palindrome? '(:a :b :c)))
+
+; http://www.4clojure.com/problem/26
+; Fibonacci Sequence
+; Write a function which returns the first X Fibonacci numbers
+(defn fibonacci [s] 
+  (#(take % (map first (iterate (fn [[a b]] [b (+ a b)]) [1 1]))) s)
+  )
+(= (fibonacci 3) '(1 1 2))
+(= (fibonacci 6) '(1 1 2 3 5 8))
+(= (fibonacci 8) '(1 1 2 3 5 8 13 21))
+
+
+; http://www.4clojure.com/problem/38
+; Maximum Value
+; Write a function which takes a variable number of parameters and returns a maximum value.
+; restrictions: max, max-key
+(defn my-max [& xs] 
+  (#(reduce (fn [a b] (if (> a b) a b)) xs))
+  )
+(= (my-max 1 8 3 4) 8)
+(= (my-max 30 20) 30)
+(= (my-max 45 67 11) 67)
+
+; http://www.4clojure.com/problem/29
+; Get the Caps
+; Write a function which takes a string and returns a new string containing only the capital letters
+(defn all-caps [s] 
+  (#(apply str (re-seq #"[A-Z]" s))))
+
+(= (all-caps "HeLlO, WoRlD!") "HLOWRD")
+(empty? (all-caps "nothing"))
+(= (all-caps "$#A(*&987Zf") "AZ")
+
+; http://www.4clojure.com/problem/48
+; Intro to some
+; The some function takes a predicate function and a collection. It returns the first logical true value of (predicate x) where x is an item in the collection.
+(= 6 (some #{2 7 6} [5 6 7 8]))
+(= 6 (some #(when (even? %) %) [5 6 7 8]))
+
+; http://www.4clojure.com/problem/32
+; Duplicate a Sequence
+; Write a function which duplicates each element of a sequence.
+
+(defn dup-seq [s]
+  (#(reverse (reduce (fn [a x] (conj (conj a x) x)) () s))))
+; or
+; mapcat #(list % %)
+; #(interleave % %)
+
+(= (dup-seq [1 2 3]) '(1 1 2 2 3 3))
+(= (dup-seq [:a :a :b :b]) '(:a :a :a :a :b :b :b :b))
+(= (dup-seq [[1 2] [3 4]]) '([1 2] [1 2] [3 4] [3 4]))
+(= (dup-seq [[1 2] [3 4]]) '([1 2] [1 2] [3 4] [3 4]))
+
+; http://www.4clojure.com/problem/47
+; Contain Yourself
+; The contains? function checks if a KEY is present in a given collection. This often leads beginner clojurians to use it incorrectly with numerically indexed collections like vectors and lists.
+(contains? #{4 5 6} 4)
+(contains? [1 1 1 1 1] 4)
+(contains? {4 :a 2 :b} 4)
+(not (contains? '(1 2 4) 4))
+
+
+; http://www.4clojure.com/problem/34
+; Implement range
+; Write a funcction which creates a list of all integers in a given range
+; restrictions: range
+(defn my-range [x y]
+  (take (- y x) (iterate inc x)))
+
+(= (my-range 1 4) '(1 2 3))
+(= (my-range -2 2) '(-2 -1 0 1))
+(= (my-range 5 8) '(5 6 7))
+
+
+; http://www.4clojure.com/problem/45
+; Intro to Iterate
+; The iterate function can be used to produce an infinte lazy sequence
+(= [1 4 7 10 13] (take 5 (iterate #(+ 3 %) 1)))
+
+; http://www.4clojure.com/problem/28
+; Flatten a Sequence
+; Write a function which flattens a sequence
+; restriction: flatten 
+
+(defn my-flatten [s] 
+  (#(filter (complement sequential?) (rest (tree-seq sequential? seq s)))))
+
+(= (my-flatten '((1 2) 3 [4 [5 6]])) '(1 2 3 4 5 6))
+(= (my-flatten ["a" ["b"] "c"]) '("a" "b" "c"))
+(= (my-flatten '((((:a))))) '(:a))
+
+; http://www.4clojure.com/problem/42
+; Factorial Fun
+; Write a function which calculates factorials.
+(defn ! [x] (if (= 1 x) 1 (* x (! (dec x)))))
+; or
+; #(apply * % (range 2 %))
+;
+(= (! 1) 1)
+(= (! 3) 6)
+(= (! 5) 120)
+(= (! 8) 40320)
+
+; http://www.4clojure.com/problem/30
+; Compress a sequence 
+; Write a function which removes consecutive duplicates from a sequence
+(defn compress-seq [s]
+            (map first (partition-by identity s)))
+
+(= (apply str (compress-seq "Leeeeeerrroyyy")) "Leroy")
+(= (compress-seq [1 1 2 3 3 2 2 3]) '(1 2 3 2 3))
+(= (compress-seq [[1 2] [1 2] [3 4] [1 2]]) '([1 2] [3 4] [1 2]))
+
+; http://www.4clojure.com/problem/
+;
+;
+
+
+; http://www.4clojure.com/problem/
+;
+;
+
+
+; http://www.4clojure.com/problem/
+;
+;
+
+
+; http://www.4clojure.com/problem/
+;
+;
+
+
+; http://www.4clojure.com/problem/
+;
+;
+
+
+; http://www.4clojure.com/problem/
+;
+;
+
+
+; http://www.4clojure.com/problem/
+;
+;
+
+
+; http://www.4clojure.com/problem/
+;
+;
+
+
+; http://www.4clojure.com/problem/
+;
+;
+
+
+
+
+(println "done")
+

src/four_clojure/scratch.clj

+(ns four-clojure.core)
+
+(#(reduce + (range 1 (inc %))) 403000000)
+(println "done")

test/four_clojure/test/core.clj

+(ns four-clojure.test.core
+  (:use [four-clojure.core])
+  (:use [clojure.test]))
+
+(deftest replace-me ;; FIXME: write
+  (is false "No tests have been written."))