Skip to content

Instantly share code, notes, and snippets.

@rivaldi8
Last active November 2, 2018 16:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rivaldi8/e33212cc740b07e6278b6c8321e4d9d7 to your computer and use it in GitHub Desktop.
Save rivaldi8/e33212cc740b07e6278b6c8321e4d9d7 to your computer and use it in GitHub Desktop.
Exercises from the book Clojure for the brave and true (http://www.braveclojure.com/)
; This is free and unencumbered software released into the public domain.
(ns chapter10.core
(require [clojure.string :as str])
(:gen-class))
(defn print-exercise-result
[exercise-function, number]
(println (str "== Exercise " number " =="))
(println (str (exercise-function) "\n")))
(defn exercise1
[]
(def atom-test (atom 0))
(swap! atom-test inc)
(swap! atom-test inc)
@atom-test)
(defn download-quote
[]
(slurp "http://www.braveclojure.com/random-quote"))
(defn add-word-counts
[total-word-count text]
(println "quote:\n" text)
(doseq [word (str/split text #" ")]
(swap! total-word-count
(fn [current-state]
(merge-with + current-state {word 1})))))
(defn create-quote-futures
[quote-count total-word-count]
(repeatedly quote-count
#(future (add-word-counts total-word-count (download-quote)))))
(defn wait-for-futures
[futures]
(dorun (map deref futures)))
(defn quote-word-count
[quote-count]
(def total-word-count (atom {}))
(wait-for-futures (create-quote-futures quote-count total-word-count))
@total-word-count)
(defn exercise2
[]
(quote-word-count 5))
(def MAX-HIT-POINTS 40)
(def character1 (ref {:name "Guybrush"
:hit-points 15
:inventory {:grog 35}}))
(def character2 (ref {:name "Elaine"
:hit-points MAX-HIT-POINTS
:inventory {:healing-potion 100}}))
(defn exercise3
[]
(def character1-before @character1)
(def character2-before @character2)
(dosync
(def needed-healing (- MAX-HIT-POINTS (:hit-points @character1)))
(alter character1 update-in [:hit-points] + needed-healing)
(alter character2 update-in [:inventory :healing-potion] - needed-healing))
(str "== Before ==\n"
character1-before "\n"
character2-before "\n"
"== After ==\n"
@character1 "\n"
@character2))
(defn -main
[& args]
(print-exercise-result exercise1 1)
(print-exercise-result exercise2 2)
(print-exercise-result exercise3 3)
(shutdown-agents))
; This is free and unencumbered software released into the public domain.
(ns mapset.core
(:gen-class))
(defn mapset
[function collection]
(loop [remaining-elements collection
new-collection #{}]
(if (empty? remaining-elements)
new-collection
(let [[head & tail] remaining-elements]
(recur tail
(into new-collection [(function head)]))))))
(defn -main
[& args]
(println (mapset #(* 10 %) [1 2 3])))
; This is free and unencumbered software released into the public domain.
(ns radial-symmetrize.core
(:gen-class))
(def asym-hobbit-body-parts [{:name "head" :size 3}
{:name "left-eye" :size 1}
{:name "left-ear" :size 1}
{:name "mouth" :size 1}
{:name "nose" :size 1}
{:name "neck" :size 2}
{:name "left-shoulder" :size 3}
{:name "left-upper-arm" :size 3}
{:name "chest" :size 10}
{:name "back" :size 10}
{:name "left-forearm" :size 3}
{:name "abdomen" :size 6}
{:name "left-kidney" :size 1}
{:name "left-hand" :size 2}
{:name "left-knee" :size 2}
{:name "left-thigh" :size 4}
{:name "left-lower-leg" :size 3}
{:name "left-achilles" :size 1}
{:name "left-foot" :size 2}])
(defn build-middle-part
[part]
{:name (clojure.string/replace (:name part) #"^left-" "middle-") :size (:size part)})
(defn build-side-part
[part side number]
{:name (clojure.string/replace (:name part) #"^left-" (str side number "-"))
:size (:size part)})
(defn radial-symmetrize
[part]
(if (clojure.string/starts-with? (:name part) "left-")
[(build-side-part part "left" 1)
(build-side-part part "left" 2)
(build-middle-part part)
(build-side-part part "right" 1)
(build-side-part part "right" 2)]
[part]))
(defn radial-symmetrize-body-parts
[asym-parts]
(reduce (fn [final-parts part]
(into final-parts (radial-symmetrize part)))
[]
asym-parts))
(defn -main
[& args]
(println (radial-symmetrize-body-parts asym-hobbit-body-parts)))
; This is free and unencumbered software released into the public domain.
(ns fwpd.core)
(def filename "suspects.csv")
(def vamp-keys [:name :glitter-index])
(defn str->int
[str]
(Integer. str))
(def conversions {:name identity
:glitter-index str->int})
(defn convert
[vamp-key value]
((get conversions vamp-key) value))
(defn is-name-present?
[record]
(contains? record :name))
(defn is-glitter-index-present?
[record]
(contains? record :glitter-index))
(def validations {:name is-name-present?
:glitter-index is-glitter-index-present?})
(defn validate
[validate-functions record]
(and ((:name validate-functions) record)
((:glitter-index validate-functions) record)))
(defn mapify
[rows]
(map (fn [unmapped-row]
(reduce (fn [row-map [vamp-key value]]
(assoc row-map vamp-key (convert vamp-key value)))
{}
(map vector vamp-keys unmapped-row)))
rows))
(defn glitter-filter
[minimum-glitter records]
(filter #(>= (:glitter-index %) minimum-glitter) records))
(defn append
[new-suspect suspects]
(if (validate validations new-suspect)
(cons new-suspect suspects)
suspects))
(defn parse
"Convert a CSV into rows of columns"
[string]
(map #(clojure.string/split % #",")
(clojure.string/split string #"\n")))
(defn map->csv
[vamp-map]
(clojure.string/join "," [(:name vamp-map) (:glitter-index vamp-map)]))
(defn map-list->csv
[map-list]
(clojure.string/join "\n" (map map->csv map-list)))
(defn -main
[& args]
(println "== Vampires ==")
(def suspects (mapify (parse (slurp filename))))
(def vamps (map :name (glitter-filter 3 suspects)))
(doall (map #(println %) vamps))
(println "\n== Vampires (v2) ==")
(def new-suspect {:name "Jander Klander" :glitter-index 4})
(def suspects-v2 (append new-suspect suspects))
(def vamps-v2 (map :name (glitter-filter 3 suspects-v2)))
(doall (map #(println %) vamps-v2))
(println "\n== Vampires (v3) ==")
(def another-new-suspect {:name "Hinkli Mincli"})
(def suspects-v3 (append another-new-suspect suspects-v2))
(def vamps-v3 (map :name (glitter-filter 3 suspects-v3)))
(doall (map #(println %) vamps-v3))
(println "*** Wrong suspect record 'Hinkli Mincli' should not appear. ***")
(println "\n== suspects (v3) CSV ==")
(println (map-list->csv suspects-v3)))
; This is free and unencumbered software released into the public domain.
(ns chapter5.core
(:gen-class))
(defn print-exercise-result
[exercise-function, number]
(println (str "== Exercise " number " =="))
(println (str (exercise-function) "\n")))
(defn exercise1
[]
(def character
{:name "Smooches McCutes"
:attributes {:intelligence 10
:strength 4
:dexterity 5}})
(defn attr
[attribute-getter]
((comp attribute-getter :attributes) character))
(str "Intelligence: " (attr :intelligence)))
(defn exercise2
[]
(defn comp-alexm
[first-function & rest-functions]
(if rest-functions
(fn [param]
(first-function ((apply comp-alexm rest-functions) param)))
#(first-function %)))
((comp-alexm #(* % 2) #(+ % 1)) 3))
(defn exercise3
[]
(defn assoc-in-alexm
[m [k & ks] v]
(if ks
(assoc m k (assoc-in-alexm {} ks v)))
(assoc m k v))
(assoc-in-alexm {:foo "bar"} [:cookie :monster :vocals] "Finntroll"))
(defn mightyfier
[mightee mighter]
(str mightee mighter))
(defn exercise4
[]
(def m {:cookie {:monster {:vocals "Finntroll"}}})
(update-in m [:cookie :monster :vocals] mightyfier " the mighty!"))
(defn exercise5
[]
(def m {:cookie {:monster {:vocals "Finntroll"}}})
(defn update-in-alexm
[m [k & ks] f & args]
(if ks
(assoc m k (apply update-in-alexm (get m k) ks f args))
(apply update m k f args)))
(update-in-alexm m [:cookie :monster :vocals] mightyfier " the mighty!"))
(defn -main
[& args]
(print-exercise-result exercise1 1)
(print-exercise-result exercise2 2)
(print-exercise-result exercise3 3)
(print-exercise-result exercise4 4)
(print-exercise-result exercise5 5))
; This is free and unencumbered software released into the public domain.
(ns chapter7.core
(:gen-class))
(defn print-exercise-result
[exercise-function, number]
(println (str "== Exercise " number " =="))
(println (str (exercise-function) "\n")))
(defn exercise1
[]
;; TODO: use read-string. Where?
(eval (list 'println "Àlex" "Alien 2")))
(defn exercise2
[]
;; TODO: implement operator precedence
(defn precedence
[operator]
(if (or (= operator "+") (= operator "-"))
0
;; * or /
1))
(defn infix
[expression]
(println "infix:" expression)
(if (= (count expression) 3)
(list (second expression) (first expression) (last expression))
(let [operand (first expression)
operator (second expression)
rest-expression (nthrest expression 2)]
(if (> (precedence operator) 0)
(list operator operand (infix rest-expression))
(list operator (infix rest-expression) operand)))))
(infix (reverse (list 1 "+" 3 "*" 4 "-" 5))))
(defn -main
[& args]
(print-exercise-result exercise1 1)
(print-exercise-result exercise2 2))
; This is free and unencumbered software released into the public domain.
(ns chapter8.core
(:gen-class))
(defn print-exercise-result
[exercise-function, number]
(println (str "== Exercise " number " =="))
(println (str (exercise-function) "\n")))
(defmacro when-valid
[data valid? & to-do]
`(when (~valid? ~data) ~@to-do))
(defn data-valid?
[data]
(> data 0))
(defn exercise1
[]
(def some-data 1)
(when-valid some-data data-valid?
(println "The data is valid!")
(println "Done!")))
(defmacro or-alexm
([] true)
([x] x)
([x & rest-expressions]
`(let [or# ~x]
(if or#
true
(or-alexm ~@rest-expressions)))))
(defn exercise2
[]
(if (and
(or-alexm false true)
(or-alexm true false)
(or-alexm false true false)
(not (or-alexm false false false)))
"OK"
"FAIL"))
(def character
{:name "Smooches McCutes"
:attributes {:intelligence 10
:strength 4
:dexterity 5}})
(defmacro defattrs
[& func-attr-pairs]
(loop [pairs func-attr-pairs
funcs '()]
(if (empty? pairs)
funcs
(let [function (first pairs)
attribute (second pairs)
rest-pairs (nthrest pairs 2)]
(recur rest-pairs (conj funcs `(def ~function
(comp ~attribute :attributes))))))))
(defn exercise3
[]
(defattrs c-int :intelligence
c-str :strength)
(str (:name character) " intelligence: " (c-int character) "\n"
(:name character) " strenght: " (c-str character)))
(defn -main
[& args]
(print-exercise-result exercise1 1)
(print-exercise-result exercise2 2)
(print-exercise-result exercise3 3))
; This is free and unencumbered software released into the public domain.
(ns chapter9.core
(:require [clojure.string :as str])
(:gen-class))
(defn print-exercise-result
[exercise-function, number]
(println (str "== Exercise " number " =="))
(println (str (exercise-function) "\n")))
(defn search-yahoo
[query]
(slurp (str "https://es.search.yahoo.com/search?q=" query)))
(defn search-wikipedia
[query]
(slurp (str "https://es.wikipedia.org/wiki/Especial:Buscar?search=" query)))
(defn search
[query]
(let [search-result (promise)]
(future (deliver search-result (search-yahoo query)))
(future (deliver search-result (search-wikipedia query)))
@search-result))
(defn exercise1
[]
(search "Enjuto"))
(def search-engines {
:yahoo "https://es.search.yahoo.com/search?q="
:wikipedia "https://es.wikipedia.org/wiki/Especial:Buscar?search="})
(defn search-in
"Searches query in the search engine and returns the HTML page as an string"
[query engine]
(slurp (str (engine search-engines) query)))
(defn search2
"Searches query in the list of search engines and returns the HTML page of
the first search engine to respond as an string"
[query engines]
(let [search-result (promise)]
(doseq [engine engines]
(future (deliver search-result (search-in query engine))))
@search-result))
(defn exercise2
[]
(search2 "Mojamuto" [:yahoo :wikipedia]))
(def href-regex #"href=\"([^\"]*)\"")
(defn get-search-result-urls
"Queries the search engine and returns a list of URLs found in the results page."
[query engine]
(map second ; second gets the grup match with the URL
(re-seq href-regex
(search-in query engine))))
(defn search3
"Queries each search engine from engines and returns a map of (search engine, urls future) pairs.
URL future are futures that when derefenced return a list of URLs found in
the results page of the search engine."
[query engines]
(zipmap engines
(map #(future (get-search-result-urls query %))
engines)))
(defn print-links
[links]
(doseq [link links]
(println " *" link)))
(defn print-search-results
[search-results-map]
(doseq [keyval-pair search-results-map]
(println "---" (key keyval-pair) "---\n")
(print-links @(val keyval-pair)))
"")
(defn exercise3
[]
(print-search-results (search3 "Enjuto" [:yahoo :wikipedia])))
(defn -main
[& args]
(print-exercise-result exercise1 1)
(print-exercise-result exercise2 2)
(print-exercise-result exercise3 3)
(shutdown-agents))
@rivaldi8
Copy link
Author

rivaldi8 commented Aug 3, 2016

If you see something wrong or that can be solved in a better way, please, add a comment :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment