99 Clojure Problems (7-10)

This is where things got both fun and difficult. These problems aren’t too difficult in F# and scala, but flatten especially confused me. Luckily, I found an example of LISP that used the mapcat function, and it basically wrote the flatten function for me. Map maps a function to a list, but mapcat assumes that the function applied to the list turns each element into a list, and then concatenates all of the items into a new list. It was confusing to say the least, but I am starting to see the power of it peeking around the corner.

; P07 (**) Flatten a nested list structure.
(defn flatten [l]
  (if (list? l)
    (mapcat flatten l)
    (list l)))

; P08 (**) Eliminate consecutive duplicates of list elements.
(comment "If a list contains repeated elements they should be 
replaced with a single copy of the element. 
The order of the elements should not be changed.")
(defn compress [l]
  (loop [current '()
         remaining l]
    (if (nil? (first remaining))
      (reverse current)
        (if (= (first current) (first remaining)) current (cons (first remaining) current)) 
        (rest remaining)))))

; P09 (**) Pack consecutive duplicates of list elements into sublists.
; If a list contains repeated elements they should be placed in separate sublists.
(defn pack [l] 
  (loop [output '()
         remaining l
         last-seen-list nil]
    (let [head (first remaining)
          tail (rest remaining)
          last-seen (first last-seen-list)]
      (nil? head) 
      (reverse (cons last-seen-list output))
      (if (= last-seen head) 
        (recur output tail (cons head last-seen-list)) 
        (recur (if (nil? last-seen-list) output (cons last-seen-list output)) tail (list head)))))))

; P10 (*) Run-length encoding of a list.
; Use the result of problem P09 to implement the so-called run-length encoding 
; data compression method. Consecutive duplicates of elements are encoded as 
; tuples (N, E) where N is the number of duplicates of the element E.
(defn encode [l] 
    (fn [a] (list (count a) (first a))) 
    (pack l)))

Unlike my first pass in scala, I’m actually doing these as they’re intended. I’m using the results of P09 to implement P10. In my scala run, I wrote each one from scratch.

99 Clojure Problems (5-6)

Clojure’s been strange so far. After tinkering in F# for the last couple months, it seems like functional programming should be easier by now.

Reverse and palindrome were easy enough, though.

; P05 (*) Reverse a list.
; clojure already has a (reverse l)
(defn s99_reverse [l]
  (loop [remain l
         curr '()] 
    (let [head (first remain)
         tail (rest remain)]
      (if (nil? head) curr (recur tail (cons head curr)))))

; P06 (*) Find out whether a list is a palindrome.
(defn isPalindrome [l] (= l (reverse l)))

I’m slowly getting my brain around the lisp like syntax, but it appears that some of the idioms are different. I’ll discuss this more when I get to the next set.

99 Clojure Problems (1-4)

I’ve been learning new languages lately, and I’ve been using the 99 scala problems to help me learn important features of the languages.

I’m going to blog about my experiences with clojure.

Once I got through the hoops of starting with clojure (just download the eclipse plugin and go!), it was smooth sailing for the first four problems.

(ns s99)
;; P01 (*) Find the last element of a list.
; Basically, this replicates the (last n) functionality already in clojure
(defn s99_last [input]
  (loop [i input]
    (let [a (first i)
          b (first (rest i))]
      (if (= b nil) a (recur (rest i))))))

; P02 (*) Find the last but one element of a list.
(defn penultimate [input] 
  (loop [i input]
	  (let [a (first i) 
	        b (first (rest i))
	        c (first (rest (rest i)))] 
	    (if (nil? c) a (recur (rest i))))))

; P03 (*) Find the Kth element of a list.
; By convention, the first element in the list is element 0.
; in clojure, nth already exists (nth n l)
(defn s99_nth [n input]
    (if (= c n) (first i) (recur (inc c) (rest i)))))

; P04 (*) Find the number of elements of a list.
; This is the same functionality as clojure's (count l) function
(defn length [input]
    (if (nil? (first i)) c (recur (inc c) (rest i)))))

So far, the lack of pattern matching makes things a little more difficult than scala or f#, but once I got a hang of the sea of parenthesis, it was easy to remember my college work with xquery.