From 66996d3f234d5dacf9056cea45a3e9d294e6fe44 Mon Sep 17 00:00:00 2001 From: John Stevenson Date: Fri, 17 Nov 2017 23:47:08 +0000 Subject: [PATCH] Added Iteration section Added content for iteration and list comprehension --- iteration/exercise-combination-lock.md | 125 +++++++++++++++++++++++++ iteration/index.md | 59 ++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 iteration/exercise-combination-lock.md create mode 100644 iteration/index.md diff --git a/iteration/exercise-combination-lock.md b/iteration/exercise-combination-lock.md new file mode 100644 index 0000000..ab064d7 --- /dev/null +++ b/iteration/exercise-combination-lock.md @@ -0,0 +1,125 @@ +# Exercise: Tubmbler Wheels Lock combinations + +You have just bought a new safe too keep all the richest you will gain from becoming a Clojure developer (hopefully). The safe has a 3 tumbler wheel combination lock to protect your new found wealth. Each tumbler wheel has the numbers 0 to 9. + +![Combination locks](/images/combination-locks.jpg) + + +> #### Note:: Represent a single combination lock +> How would you represent the possible numbers in just one of the tumbler wheels +```eval-clojure +[] +``` + + + +* The combination is managed by three tumbler wheels +* Each tumbler wheel has the same range of numbers on then, 0 to 9 + +Each tumbler wheel could have all the numbers it contains within a _Collection_ in Clojure. The simplest approach would be to put the numbers 0 to 9 into a Vector (an array-like collection). + +~~~clojure +[0 1 2 3 4 5 6 7 8 9] +~~~ + + + +------------------------------------------ + +> #### Note::Generating the number range +> As the numbers on the tumbler wheel are just a range between 0 and 9, then rather than type out all the numbers, is there a function to generate all the numbers for us. +```eval-clojure +() +``` + + + +When we give the range function one argument, it will create all the whole numbers from 0 to the number before that of the argument. In the following example, we give `range` the argument of 10 and we receive the numbers from 0 to 9. + +~~~clojure +(range 10) +~~~ + +You can also give `range` two arguments, such as '(range 5 15)'. + +> Be careful not to call the `range` function by itself, or it will try and generate an infinite range of numbers (until your computer memory is all used up). + + + + + +------------------------------------------ + +> #### Note::Create all the Combinations +> Generate all the possible combinations of the lock using three tumbler wheels +> We have given you a bit of a clue +```eval-clojure +(for [tumbler-one (range 10)] +) +``` + + + +~~~clojure +(for [tumbler-1 (range 10) + tumbler-2 (range 10) + tumbler-3 (range 10)] + [tumbler-1 tumbler-2 tumbler-3]) +~~~ + + + +------------------------------------------ + +> #### Note::Total number of combinations +> You did the hard work already, now return just the total number of combinations +```eval-clojure +() +``` + + + +Take the code from the combinations and wrap it in the count function + +~~~clojure +;; now count the possible combinations +(count + (for [tumbler-1 (range 10) + tumbler-2 (range 10) + tumbler-3 (range 10)] + [tumbler-1 tumbler-2 tumbler-3])) +~~~ + + + +------------------------------------------ + +> #### Note::Make the combinations harder to guess +> To make our lock harder to break into, we should only allow the combinations where each tumbler wheel has a different number. So you should exclude combinations like 1-1-1, 1-2-2, 1-2-1, etc. +> +> How many combinations does that give us? +```eval-clojure +() +``` + + + + +**Complete the following code to create a 3-tumbler wheel combination lock, where none of the numbers are the same** + +> Hint: Beware not to enter (range) without an argument as Clojure may try and evaluate infinity + +~~~clojure +(count + (for [tumbler-1 (range 10) + tumbler-2 (range 10) + tumbler-3 (range 10) + :when (or (= tumbler-1 tumbler-2) + (= tumbler-2 tumbler-3) + (= tumbler-3 tumbler-1))] + [tumbler-1 tumbler-2 tumbler-3])) +~~~ + +Here is a [suggested example](https://gist.github.com/ab1f8d4561cc2b8b3e51887dd2519a18) of the completed 3-lock challenges. + + diff --git a/iteration/index.md b/iteration/index.md new file mode 100644 index 0000000..92924b3 --- /dev/null +++ b/iteration/index.md @@ -0,0 +1,59 @@ +# Iteration + +Iteration is the art of processing all the values in a collection and doing something with each of those values in turn. + +We have already used `map`, `reduce` & `apply` to iterate over the values in a collection. + +## `for` function + +The `for` function helps us work with each value in a collection. + +As an example, we can use the `for` function to generate the mathematical squares for the numbers 1 to 9 + +```eval-clojure +(for [number (range 1 10)] + (* number number)) +``` + +In the above example, `number` is a local name that is used to refer in turn to each value in our collection. + +## assignment & conditions + +We can assign additional local names within the `for` function, using the `:let` directive. Each iteration the name in the `:let` is bound to a new value. + +Conditions can be used to filter our results using `:when`, only returning values that match the condition. + +```eval-clojure +(for [number [0 1 2 3 4 5] + :let [result (* number 3)] + :when (even? result)] + result) +``` + + + +## Lisp comprehension + +In Clojure, list comprehension is via the [for](https://clojuredocs.org/clojure.core/for) function + +* Clojure docs: [for](https://clojuredocs.org/clojure.core/for) +* Reference: [Lisp Comprehension in Clojure](https://practicalli.github.io/clojure/thinking-functionally/list-comprehension.html) - Clojure, practicalli + + + + +## `for` is a macro + +Macros can be used just like functions. However, before a macro runs it alters its code to new Clojure code. + +A macro can let us write short-cuts in our code, like we did with the `:let` and `:where` lines in the second example on this page. + +Macros are a very powerful way of keeping the language of Clojure as simple as possible. Macros also let developers extend Clojure without having to wait for the language designers. + +Macros are very powerful so developers are encouraged to keep their use to a minimum. Most Clojure developers will never need to write a macro. + + +> #### Hint::Iteration & Recursion +> In simple terms, an iterative function is one that loops to repeat some part of the code and a recursive function is one that calls itself again to repeat the code. +> +> Read more about recursion at [Recursion 101 by PurelyFunctional.tv](https://purelyfunctional.tv/courses/recursion-101/)