Last active
November 2, 2018 16:20
-
-
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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If you see something wrong or that can be solved in a better way, please, add a comment :-)