Skip to content

Instantly share code, notes, and snippets.

@noahlz
Created December 23, 2011 23:02
Show Gist options
  • Save noahlz/1515617 to your computer and use it in GitHub Desktop.
Save noahlz/1515617 to your computer and use it in GitHub Desktop.
LabRepl looping exercises
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; LabREPL min-3 exercise
;; "Implement min-3 which reduces over a function that returns
;; the min of two arguments"
;; My attempt
(defn min-3 [x & more]
(let [s (cons x (seq more))]
reduce (fn findmin [x y] (if (< x y) x y)) s)))
;; #'user/min-3
(min-3 1 2 3 4)
;; 1
(min-3 1 2 3 -4)
;; -4
(min-3 1 2 3 -7 -8 32 -100 12 4 1000)
;;-100
;; Solution
(defn min-3 [& coll]
(reduce (fn [x y] (if (< x y) x y)) coll))
;; #'user/min-3
(min-3 1 2 3 -7 -8 32 -100 12 4 1000)
;; -100
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; LabREPL zipm exercises
;; "One option is to loop over three variables: the result map m (which gets
;; bigger), and the input sequences ks and vs (which get smaller). Create a
;; zipm-1 that uses a loop and assoc to build the result map."
;; My implementation - forgot that keys and values might not be sequences.
(defn zipm-1 [keys values]
(loop [[k & ks] keys
[v & vs] values
m {}]
(if (and k v)
(recur ks vs (assoc m k v))
m)))
;; #'user/zipm-1
(zipm-1 [:a :b :c] [1 2 3])
;; {:c 3, :b 2, :a 1}
(zipm-1 [:d :a :b :c] [1 2 3 4])
;; {:c 4, :b 3, :a 2, :d 1}
;; The solution...
(defn zipm-2
[keys vals]
(loop [m {}
[k & ks :as keys] (seq keys)
[v & vs :as vals] (seq vals)]
(if (and keys vals)
(recur (assoc m k v) ks vs)
m)))
;; I actually implemented the solution for zipm-2...
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; LabREPL minmax exercise
;; Implement minmax-2 using reduce. Think carefully about the reduction
function. It needs to hold two values at each iteration: one each for min and max.
(defn minmax-2
[& coll]
(reduce (fn [m val]
(let [oldmin (if m (:min m) nil)
oldmax (if m (:max m) nil)
newmin (if oldmin (if (< val oldmin) val oldmin) val)
newmax (if oldmax (if (> val oldmax) val oldmax) val)]
(assoc {} :min newmin :max newmax))) {} coll))
(minmax-2 1 2 3 4 5)
;; {:max 5, :min 1}
(minmax-2 -100 2 87 29 1000 284 29)
;; {:max 1000, :min -100}
(minmax-2 -100 2 87 29 1000 284 29 -10000000 1/2)
;; {:max 1000, :min -10000000}
;; The solution - merge-with FTW
(defn minmax-2
[x & more]
(reduce
(fn [result x]
(->> result
(merge-with min {:min x})
(merge-with max {:max x})))
{:min x :max x}
more))
;; NOTE - the ->> makes the above roughly equivalent to the following:
(defn minmax-2
[x & more]
(reduce (fn [result x]
(merge-with min {:min x} (merge-with max result {:max x})))
{:min x :max x}
more))
(minmax-2 -100 2 87 29 1000 284 29 -10000000 Integer/MAX_VALUE)
;; (:min -10000000, :max 2147483647}
(minmax-2 -100 2 87 29 1000 284 29)
;; {:min -100, :max 1000}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment