Showing posts with label 99-clojure-problems. Show all posts
Showing posts with label 99-clojure-problems. Show all posts

Saturday, May 28, 2016

99 Clojure Problems – 63: Construct a Complete Binary Tree

"A complete binary tree with height H is defined as follows: The levels 1,2,3,...,H-1 contain the maximum number of nodes (i.e 2(i-1) at the level i, note that we start counting the levels from 1 at the root). In level H, which may contain less than the maximum possible number of nodes, all the nodes are 'left-adjusted'. This means that in a levelorder tree traversal all internal nodes come first, the leaves come second, and empty successors (the Ends which are not really nodes!) come last.

Particularly, complete binary trees are used as data structures (or addressing schemes) for heaps.

We can assign an address number to each node in a complete binary tree by enumerating the nodes in levelorder, starting at the root with number 1. In doing so, we realize that for every node X with address A the following property holds: The address of X's left and right successors are 2*A and 2*A+1, respectively, supposed the successors do exist. This fact can be used to elegantly construct a complete binary tree structure. Write a method completeBinaryTree that takes as parameters the number of nodes and the value to put in each node."

Example

ninety-nine-clojure.bintrees> (complete-binary-tree 6 'x)                                 |
[x [x [x nil nil] [x nil nil]] [x [x nil nil] nil]]

A simple not-stack-safe approach uses recursion. One key insight here is to see that the address of the node is also at the same time the discriminator to terminate the recursion in the base case. If the address of the node we are going to construct would exceed the desired size of the tree we have to stop. This property holds also for the multiple recursion we are doing when constructing the branches of the binary tree.

Verify

You can verify the completeness of your tree by writing a predicate. My solution is a translation of the Haskell solutions of the 99 problems

This predicate verifies that the first empty slot in a node comes after the last populated node which is another way of expressing the completeness property.

(defn complete-tree? [t]
  (let [minmax (fn minmax [[v l r] idx]
                 (cond
                   (nil? v) [0 idx]
                   :else (let [[max-l min-l] (minmax l (* 2 idx))
                               [max-r min-r] (minmax r (inc (* 2 idx)))]
                           [(max idx max-l max-r) (min min-l min-r)])))]
    (apply < (minmax t 1))))

A Note on Design Decisions

While working on this predicate a design decision made early on in this section on trees bit me. By using Clojure's nil to express the emptiness of a node I overloaded (or 'complected' to parrot Rich Hickey's choice of words) the meaning of nil (nothing) to also express the absence of a child node in the tree and the empty tree. My traversal functions ignore nil, collapse it or elude it when concatenating branches of the tree for traversal. This is usually not a problem when you are only interested in the values of your tree. But here we want to know when in the levelorder traversal the first nil appears.

I thought a bit about this and came to the conclusion that the effects of that choice could have been mitigated by choosing a more expressive representation of the tree. My vector based approach is very minimal and works nicely in many cases because it relies on the seq abstraction. Vector destructuring works even with nil because nil seems to support nth. By creating a record or a map we can still destructure and be succinct in the handling of the tree but solve problems like determining the first occurrence of nil without resorting to a reimplementation of traversal.

Read more about this series.

Sunday, March 20, 2016

99 Clojure Problems – 62B: Collect the Nodes at a Given Level in a List.

"A node of a binary tree is at level N if the path from the root to the node has length N-1. The root node is at level 1. Write a method at-level to collect all nodes at a given level in a list."
(deftest p62b-at-level
  (is (= '(b c) (at-level '[a [b nil nil] [c [d nil nil] [e nil nil]]] 2))))

The basic idea for the solution was to see the tree as a list of nodes and to realise that the nodes at a given level start at node 2^(level - 1) and that this is also the size of each level. Solution on Github.

Read more about this series.

Tuesday, March 08, 2016

99 Clojure Problems – 61A: Collect the Leaves of a Binary Tree in a List

"61A (*) Collect the leaves of a binary tree in a list. A leaf is a node with no successors. Write a method leaves to collect them in a list."

(deftest p61a-leaves
  (is (= '(b d e) (leaves '[a [b nil nil] [c [d nil nil] [e nil nil]]]))))

A variation on the previous exercise. Solution.

Read more about this series.

Wednesday, March 02, 2016

99 Clojure Problems – 62: Collect the Internal Nodes of Binary Tree in a List

"An internal node of a binary tree has either one or two non-empty successors. Write a method internals to collect them in a list."
(deftest p62-internals
  (is (= '(a c) (internals '[a [b nil nil] [c [d nil nil] [e nil nil]]]))))

I used the same idea as in the two previous exercises: walk the tree and filter, just filtering for branch nodes this time. Again using a predicate I wrote earlier. Solution on Github.

Read more about this series.

Sunday, February 21, 2016

99 Clojure Problems – 61: Count the Leaves of a Binary Tree.

"A leaf is a node with no successors. Write a method leaf-count to count them."

(deftest p61-count-leaves
  (is  (= (leaf-count '[x [x [x nil nil] nil] [x nil nil]]) 2)))

I simply walked the tree and counted all the leaves. Both functions, for detecting leaves and walking the tree, existed from previous exercises. See the solution on Github.

Read more about this series.

Wednesday, February 17, 2016

99 Clojure Problems – 60 (alternative solution): Construct Height-balanced Binary Trees with a Given Number of Nodes.

This post describes an alternative solution to problem 60 based on logic programming. Check out my previous post for a functional Clojure solution.

The original 99 problems were compiled to teach Prolog. Clojure's core.logic implements a minimal logic DSL called miniKanren using Clojure as the host language. In this post I reimplement the solution to problem 60 based on core.logic. If you want to learn more about miniKanren 'The Reasoned Schemer' and minikanren.org are probably good places to start.

My solution is not fully relational, I rely on the groundness of certain terms. See the comments below. Full source can be found on Github.

"Construct height-balanced binary trees with a given number of nodes. Consider a height-balanced binary tree of height H. What is the maximum number of nodes it can contain? Clearly, MaxN = 2H - 1.

However, what is the minimum number MinN? This question is more difficult. Try to find a recursive statement and turn it into a function min-hbal-nodes that takes a height and returns MinN."

(defne min-nodes [h n]
  ([0 0])
  ([1 1])
  ([h n]
   (fd/> h 1)
   (fresh [h1 h2 n1 n2]
     (is h1 h dec)
     (is h2 h1 dec)
     (min-nodes h1 n1)
     (min-nodes h2 n2)
     (fd/in n1 n2 n (fd/interval 0 Integer/MAX_VALUE))
     (fd/eq (= (+ 1 n1 n2) n)))))

(defn min-hbal-nodes  
  [h]
  (run 1 [q]
    (min-nodes h q)))

"On the other hand, we might ask: what is the maximum height H a height-balanced binary tree with N nodes can have?"


(defne max-height [n h h1 n1]
  ([n h h1 n1]
   (fd/> n1 n)
   (is h h1 dec)) ;;non-relational
  ([n h h1 n1]
   (fd/<= n1 n)
   (fresh [h2 n2]
     (is h2 h1 inc)
     (min-nodes h2 n2)
     (max-height n h h2 n2))))

"Now, we can attack the main problem: construct all the height-balanced binary trees with a given nuber of nodes."


(defne num-nodes [t n]
  ([nil 0])
  ([[_ l r] n]
   (fresh [nl nr]
     (num-nodes l nl)
     (num-nodes r nr)
     (fd/in nl nr n (fd/interval 0 Integer/MAX_VALUE))
     (fd/eq (= (+ 1 nl nr) n)))))

(defne min-height [n h]
  ([0 0])
  ([n h]
   (fresh [n1 h1]
     (fd/in n1 (fd/interval 0 Integer/MAX_VALUE))
     (fd/> n 0)
     (project [n n1]
              (== (quot n 2) n1)) ;; non-relational
     (min-height n1 h1)
     (fd/+ h1 1 h))))


(defn hbal-tree-nodes [n t]
  (fresh [hmin hmax h]
    (min-height n hmin)
    (max-height n hmax 1 1)
    (fd/>= h hmin)
    (fd/<= h hmax)
    (hbal-tree h t);; requires solution to P59
    (num-nodes t n)))

(defn all-hbal-trees [n]
  (run* [q]
    (hbal-tree-nodes n q)))

Usage:

ninety-nine-clojure.bintrees> (min-hbal-nodes 4)
7
ninety-nine-clojure.bintrees> (all-hbal-trees 4 )
([x [x [x nil nil] nil] [x nil nil]] [x [x nil nil] [x [x nil nil] nil]] [x [x nil [x nil nil]] [x nil nil]] [x [x nil nil] [x nil [x nil nil]]])

Read more about this series.

Saturday, January 16, 2016

99 Clojure Problems – 60: Construct Height-balanced Binary Trees with a Given Number of Nodes.

"Construct height-balanced binary trees with a given number of nodes. Consider a height-balanced binary tree of height H. What is the maximum number of nodes it can contain? Clearly, MaxN = 2H - 1.

However, what is the minimum number MinN? This question is more difficult. Try to find a recursive statement and turn it into a function min-hbal-nodes that takes a height and returns MinN.

On the other hand, we might ask: what is the maximum height H a height-balanced binary tree with N nodes can have?

Now, we can attack the main problem: construct all the height-balanced binary trees with a given nuber of nodes."

Example:

ninety-nine-clojure.bintrees> (min-hbal-nodes 4)
7
ninety-nine-clojure.bintrees> (all-hbal-trees 4 'x)
([x [x [x nil nil] nil] [x nil nil]] [x [x nil nil] [x [x nil nil] nil]] [x [x nil [x nil nil]] [x nil nil]] [x [x nil nil] [x nil [x nil nil]]])

Discussion

The solution to problem 60 builds upon the solution to problem 59, so if you have not done that one yet, now would be a good time.

As always I don't want to give away the solution in the blog post right away to give you a chance to try it yourself first. But if you get stuck, it is all on Github.

Approach

The question contains a hint towards a possible solution but it was not immediately clear to me how the minimum number of nodes at a given height MinN helps us in finding all height-balanced trees with a given number of nodes.

It helped me to explore the problem starting with the expected result and progressing to the intermediate computations mentioned in the problem description later: What do we want to achieve and which parts do we have already?

  1. We have a method "height-balanced-trees" to calculate all height-balanced trees with a certain height from P59.
  2. We could now just filter the result of calling this existing function, leaving those trees in the result that have the required number of nodes and have the desired solution to problem 60.
  3. But at which height do we start generating trees and where do we stop? We cannot generate trees for all possible heights.
  4. Working our way back towards the beginning of the question, we could use the maximum height H of a tree with a given number of nodes as the upper bound of the input to the "height-balanced-trees" function from problem 59.
  5. That leaves us with the missing lower bound: What is the minimum height of a tree with a given number of nodes? We need another function to answer that question. Let's start with that one.

Minimum Height of a Tree with a Given Number of Nodes

If we recursively half the given number of nodes and keep track of how many times we did that we have the minimum height, because it is a height-balanced binary tree. But we could also exploit the fact that the height of a balanced binary tree of n nodes is log2 n + 1.

Maximum Height of a Tree with a Given Number of Nodes

Now this part is a bit trickier. We now need to know what the minimum number of nodes at a given height is, as indicated in the question. Why? Let's look at the number of nodes for all the trees at a given height:

H=3: (4 5 6 7)
H=4:       (7 8 9 10 11 12 13 14 15)
H=5:                   (12 13 14 15 16 17 18 19 20 ...

To pick an interesting example: A tree with seven nodes is at most four levels high. We know that because the minimum number of nodes at height five is greater than seven. If we look at all MinN for increasing heights and stop when MinN gets bigger then our N, we know that the previous height is the maximum height we are looking for.

Now how do we calculate the MinN? Interestingly the MinN(H) is always the MinN(H-1) + MinN(H-2) +1. A formula that seems like a twist on the Fibonacci sequence. I don't have a good intuition as to why this is, but you can just derive this rule by looking at trees with small Hs.

The mentioned formula translates nicely into a recursive function.

Solution and Outlook

Putting it all together is then relatively straight forward. So much so that I will share the code right here:

(defn all-hbal-trees
  "P60 (**)  ... Now, we can attack the main problem: construct all the
  height-balanced binary trees with a given nuber of nodes."
  [n v]
  (->>  (range (min-height-hbal n) (inc (max-height-hbal n)))
        (mapcat #(height-balanced-trees % v))
        (filter #(= n (num-nodes %)))))

Reusing the code from problem 59 is certainly nice but this solution seemed rather wasteful to me as we are throwing away many intermediate results in the filter step. Feeling a bit underwhelmed by my solution I started exploring the original Prolog solution to the problem and reimplemented it using David Nolen's core.logic library. We will cover this additional experiment in the next post.

Read more about this series.

Thursday, June 11, 2015

99 Clojure Problems – 59: Construct Height-Balanced Binary Trees

"In a height-balanced binary tree, the following property holds for every node: The height of its left subtree and the height of its right subtree are almost equal, which means their difference is not greater than one.

Write a method to construct height-balanced binary trees for a given height with a supplied value for the nodes. The function should generate all solutions."

Example

ninety-nine-clojure.bintrees> (height-balanced-trees 2 'x)
([x [x nil nil] [x nil nil]] [x [x nil nil] nil] [x nil [x nil nil]])

Discussion

To get some intuition for this problem we can distinguish tree cases:
  1. The left subtree has the same length as the right subtree
  2. The left subtree is shorter by one level
  3. The right subtree is shorter by one level
If we combine all three cases via concat we have our solution. We generate the solutions by recursively calling the function with the heights h-1 and h-2. We don't have to generate the 'short' versions of the left and right subtrees separately. We can just create both combinations (left shorter/right shorter) with just one copy of the lower subtrees (h-2) and one copy of the higher subtrees (h-1). Still, there is some redundant computation going on as the h-1 contains also the h-2 subtrees. Memoization might help here.

The practical applicability of the function just created as described is somewhat limited as the number of height balanced binary trees grows exponentially. For our test case we therefore just look at trees up to five levels high.

Read more about this series.

Saturday, May 30, 2015

99 Clojure Problems – 58: Generate-and-Test Paradigm

"Apply the generate-and-test paradigm to construct all symmetric, completely balanced binary trees with a given number of nodes.

How many such trees are there with 57 nodes? Investigate about how many solutions there are for a given number of nodes? What if the number is even? Write an appropriate function."

Example

>(symmetric-cbalanced-trees 5 'x)
([x [x nil [x nil nil]] [x [x nil nil] nil]] [x [x [x nil nil] nil] [x nil [x nil nil]]])

Discussion

A simple approach just filters the output of our existing function for completely balanced trees using the also existing symmetric? predicate.

A simple optimisation is to avoid the tree generation all together if the number of nodes requested is even, as there is no symmetric tree with an even number of nodes.

Solution on Github.

Read more about this series.

Thursday, May 21, 2015

99 Clojure Problems – 56: Symmetric Binary Trees

"Let us call a binary tree symmetric if you can draw a vertical line through the root node and then the right subtree is the mirror image of the left subtree. Write a predicate symmetric/1 to check whether a given binary tree is symmetric. Hint: Write a predicate mirror/2 first to check whether one tree is the mirror image of another. We are only interested in the structure, not in the contents of the nodes."

Example/Test

(deftest p56-symmetric-binary-trees
  (is (= true (symmetric? [:a [:b nil nil] [:c nil nil]])))
  (is (= false (symmetric? [:a nil [:b nil nil]]))))

Discussion

This is a two star problem but once the implications of 'symmetry' in this case become clear, it is not hard at all to solve.

If we think about the tree it is obvious that we cannot establish the property of symmetry just by looking at the node count. Symmetry seems to be stricter in that it not only requires the same number of nodes in each subtree but they also have to be mirror images of each other. This is already implied in the hint given to us in the problem description.

Another way of putting it is that the leaves of the subtrees we compare have to be in the mirrored position respectively. One way to find that out is to recursively inspect both subtrees and make sure that there is a leaf in left tree when there is also a leaf in the right tree.

This led to this solution, which is incorrect.

Nil-Punned

The reason this first solution does not work as expected is that I have overloaded the meaning of nil. It represents the absence of a subtree and the empty tree. But I have also created the helper functions 'lefts' and 'rights' to extract the left or right subtrees respectively. As they rely on the seq abstraction through 'first', 'next' and 'last', nil now can be also the result of retrieving one of the subtrees.

There is no way to decide if the nil we get back means now 'there is no subtree' or 'there is no subtree because there is no tree in the first place'. But exactly this distinction is important when we want to determine the symmetry property of the data structure.

(Data) Structure

Pattern matching using core.match on the structure of the tree allows us to overcome this problem and distinguish the different cases more clearly. Nil as the empty tree never matches the pattern for a tree node. We do not need the different helper functions anymore as we are now working directly with the structure of our data.

You can find this amended solution on Github.

Read more about this series.

99 Clojure Problems – 57: Binary Search Trees

Write a function insert-val to add elements to a binary search tree. Then write a function to construct a binary search tree from a list of integer numbers. Then use this function to test the solution of the problem P56.

Example

>(->binary-search-tree 3 2 5 7 1)
[3 [2 [1 nil nil] nil] [5 nil [7 nil nil]]]
>(->binary-search-tree 5, 3, 18, 1, 4, 12, 21)
[5 [3 [1 nil nil] [4 nil nil]] [18 [12 nil nil] [21 nil nil]]]
> (symmetric? *1)
true

Discussion

I feel almost bad about the number of times I have resorted to core.match to solve these problems. Maybe I am just not thinking hard enough about alternative approaches. What it certainly tells us is that pattern matching seems to lend itself very well to this class of problems.

Pattern Match All The Things

Four match clauses seem to do the trick (number three is technically split into two) :

  1. Adding nil to a tree is just the tree.
  2. Adding a value to nil is a new tree of one node
  3. Adding a non-nil value to a non-nil tree: Now it depends on the ordering of the values: is the value greater than the value at the current node: add it to the right subtree, else add it to the left subtree.

What about adding the same value twice? I do not think binary search trees are per se opinionated about how to handle duplicates. In my implementation duplicate values just end up to the right of the value they are identical with. I think it would also be very plausible to make insert-val a no-op if the value is already contained in the tree.

Putting it all together

Constructing the tree seems trivial using the insert-val function we have just constructed. Clojure's reduce is equivalent to a 'fold left' over the input collection. If we reduce the input values with insert-val using nil as the neutral element we get the desired result.

My solution can be found, as always, on Github.

Read more about this series.

Sunday, May 17, 2015

99 Clojure Problems – 55: Construct Completely Balanced Binary Trees

"In a completely balanced binary tree, the following property holds for every node: The number of nodes in its left subtree and the number of nodes in its right subtree are almost equal, which means their difference is not greater than one."

Example

>(balanced-trees 3 'x)
([x [x nil nil] [x nil nil]])

Verification

(defspec balanced-trees-are-balanced
  20
  (prop/for-all [i gen/nat]
                (->> (balanced-trees i 'x)
                     (apply  breadth-first-traverse)
                     (map balanced?)
                     (reduce #(and %1 %2)))))

Discussion

The following observations lead to a possible solution:

  1. We can enumerate all the trees by combining the root node with all its possible subtrees to the left and to the right which have in sum \(n-1\) nodes
  2. We distinguish between even and odd values of n
  3. Odd values of n give balanced trees as \(n-1\) is even and both subtrees will be of equal size
  4. Even values of n give balanced trees if we return all combinations of left/right trees with \((n-1) / 2\) and \((n-1) / 2 + 1\) nodes. We are using integer division here, thereby effectively 'flooring' and 'ceiling'

Based on this understanding the implementation is fairly straightforward. We handle the base case of an empty tree separately and then the two cases for odd and even number of nodes.

There is a little bit of ceremony involved in order to create the combinations of subtrees in the case of odd-sized subtrees. You have to do a nested mapcat to get both variants with the longer subtree in left and right position respectively. Maybe there is room for improvement.

I found it instructive to look at the Haskell and Prolog solutions in order to get a better understanding. The latest version of my code tries to come close to the clarity of the Prolog solution.

Read more about this series.

Friday, April 03, 2015

99 Clojure Problems-54: Is This A Binary Tree?

"Write a predicate tree? that succeeds if and only if its argument is representing a binary tree."

Example/Test

(deftest nil-is-a-tree
  (is (= true (tree? nil))))

Discussion

This is an interesting problem because it allows us to touch the basic question of static vs. dynamic typing.

If we look at the Scala solution, we see that in a statically typed language this problem can be fully solved via the type system. Or as Phil Gold put it: "Score one for static typing."

I am not a zealot when it comes to static vs. dynamic typing. Both approaches have their merits. There are many ways to look at this (prototyping, easier code reuse vs. working with legacy code, catching errors early ...). Maybe it is a very narrow perspective but for me it is almost more of a social than a technical issue. I see how a team of developers with mixed skill levels in combination with a code base in various stages of decay can benefit from a compiler giving them more guidance along the way through the maze. On the other hand, I have never missed the absence of a strict type system in Clojure when quickly building prototypes or solving programming problems. While I am still on the fence about the general issue of static vs. dynamic type systems, let us look at the problem at hand: working with binary trees.

The Dynamic Approach

We can solve this problem in a "dynamic" fashion building upon what we have done so far in this series. We worked with trees before for problem 25 using a library called core.match, which gives us pattern matching in Clojure to implement all the tree operations.

With core.match we get the tree?-predicate with a simple three way pattern match: it is either a node consisting of a label and two subtrees or nil representing the empty tree. Everything else is not a tree. The only complication is that we need to apply the pattern match for the node recursively, because the left and right subtrees should also be proper trees. Luckily, core.match supports function application in match expressions since 0.3.0.

Have a look at the solution and the accompanying tests to the get the idea.

Best of Both Worlds?

In Clojure we have a second option because, while being dynamic as a language, it offers us optional static typing in the form of a library called core.typed. The library is the result of the work Ambrose Bonnaire-Sergeant did for his PhD dissertation.

It allows us to declare a type Node consisting of a label of any kind and two children that are trees themselves. A tree is now either an empty tree (represented by nil) or one of these nodes.


(t/ann-datatype Node [val :- Any
                      l   :- Tree
                      r   :- Tree])
(deftype Node [val l r])

(t/defalias Tree
  (t/Nilable Node))

To make this work, all you have to do is include core.typed as a library dependency in your project.clj (assuming you are using leiningen as your build tool). The type checking is not part of the compilation but an extra step you have to integrate into your workflow. Editor integrations for vim, Emacs and LightTable make it easier to construct your type system during development.

It helps to look at the core.typed example code (even if you are familiar with static typing) to work out how to apply the type annotations.

The Choice Is Yours

Clojure seems to give us the choice between both (optional) static and dynamic typing. If time allows, I will try to follow this dual path through all the binary tree problems to gain more insight into both approaches.

Read more about this series.

Wednesday, December 31, 2014

99 Clojure Problems-50: Huffman Code

Example

(deftest huffmann
  (is (= '([a "0"] [c "100"] [b "101"] [f "1100"] [e "1101"] [d "111"])
         (-> '([a 45] [b 13] [c 12] [d 16] [e 9] [f 5])
             build-huffman-tree
             map-symbols))))

Discussion

Huffman coding is a variable length coding based on the frequency of each possible source value. You might have a look at the wikipedia article (or a good book on discrete mathematics and/or algorithms as suggested on the original "99 problems" page) to get a basic understanding of what we are trying to do here.

I used a variation of the two queues method: one queue for the initial set of leaf nodes, the other for the aggregate or branch nodes. The queues have to be ordered by ascending frequency. If you can use a priority queue that does the ordering for you that's fine. You then dequeue the two items with the lowest frequency from each queue (or from just one queue if the other is empty) and combine the two leaves into a branch node. You continue with this procedure until there is only one node left, which is your Huffman tree.

Have a look at the code, but, as usual, first try it yourself. I'm not entirely happy with my solution, which seems to be correct, but some of its semantics are rather subtle. Did you spot that the check for an empty queue is implicit in the default value of Long/MAX_VALUE when accessing the next value polled from the queue? As always, I am happy to get feedback on the solutions presented.

This is the last post for 2014. I set out at the beginning of the year to solve all 99 problems in Clojure that were mentioned in the original 99 Prolog problems compilation. I managed to do the first 50 and I really enjoyed them. Nevertheless, when learning a new language, solving these kinds of nicely prepared educational problems takes you only half the way. I think that the next step should be to build an actual system in Clojure. I still found doing these exercises rewarding and useful, as they allow me to do some Clojure in the limited spare time I have. I am going to continue with the series next year hoping to solve the remaining problems.

Tuesday, October 28, 2014

99 Clojure Problems – 49: Gray Code

"An n-bit Gray code is a sequence of n-bit strings constructed according to certain rules. For example:

n = 1: C(1) = ("0", "1").
n = 2: C(2) = ("00", "01", "11", "10").
n = 3: C(3) = ("000", "001", "011", "010", "110", "111", "101", "100").

Find out the construction rules and write a function to generate Gray codes. See if you can use memoization to make the function more efficient."

Example/Test

deftest gray-2
  (is (= ["00" "01" "11" "10"] (gray 2))))

(deftest gray-3
  (is (= ["000" "001" "011" "010" "110" "111" "101" "100"] (gray 3))))

Discussion

I did not work out the construction rules myself but simply looked at Wikipedia. I recommend to read the relevant article yourself before continuing. Based on my reading I came up with two solutions.

The first solution follows the name giving generative principle of forming new lists of gray codes by reflecting existing sublists. Or more precisely from Wikipedia:

"The binary-reflected Gray code list for n bits can be generated recursively from the list for n−1 bits by reflecting the list (i.e. listing the entries in reverse order), concatenating the original list with the reversed list, prefixing the entries in the original list with a binary 0, and then prefixing the entries in the reflected list with a binary 1"

This lead to an immediate translation into code based on strings as can be seen on Github.

Adding memoization as requested by the exercise is very easy in Clojure as there is a dedicated memoize function that returns a memoized version for a referentially transparent function.

Leaving aside the inefficiencies of this solution there is a more immediate problem with this implementation because it is not "stack safe". That means for every recursive step a new stack frame will be created and the code will only unwind the stack when it has reached the exit condition leading to a stack overflow for deep recursive calls. Using the gray code example, depending on your VM configuration and whether or not you are using memoization, you start running into trouble around 20 bits or so.

The second solution is based on the gray code conversion algorithm whereby you convert binary to gray code by xor'ing the binary number with itself right shifted by one. The only complication is that you have to calculate the range of possible numbers first. This is 2^n where n is the number of bits you want to support in your gray code encoding.

You calculate an exponent in Clojure by literally multiplying the number as many times as the exponent states:

(reduce * (repeat n 2))
or use a library like numeric-tower that features an exponent function. To create the identical output as the string based version I used the common lisp formatting build into clojure.pprint:
(cl-format nil (str "~" n "'0b") %)
This allows me to print the binary/gray code elegantly left padded with zeros. Alternatively you could use Java interop with String.format and Long.toBinaryString.

There is probably more to be said about gray code and there are more efficient solutions. The two main takeaways here on the language level are how easy it is in Clojure to create a memoized function and the possibility to use Common Lisp formatting instead of Java's if it seems more appropriate.

Read more about this series.

Wednesday, August 20, 2014

99 Clojure Problems – 48: Truth Tables for Logical Expressions (3)

Generalize problem 47 in such a way that the logical expression may contain any number of logical variables. Define table in a way that (table vector expr) prints the truth table for the expression expr, which contains the logical variables enumerated in vector.

Example

ninety-nine-clojure.logic> (table (i [a b c], (a and (b or c) equ a and b or a and c)))

|    :a |    :b |    :c | :result |
|-------+-------+-------+---------|
|  true |  true |  true |    true |
|  true |  true | false |    true |
|  true | false |  true |    true |
|  true | false | false |    true |
| false |  true |  true |    true |
| false |  true | false |    true |
| false | false |  true |    true |
| false | false | false |    true |

Discussion

This is more of a refactoring of the previous solution than anything else. I learned a bit more about how macros work in Clojure and discovered that some of the problems I solved last time were actually non-problems.

There are three places in our current code that prevent us from specifying expressions with arbitrary many logical variables: The input values were hard-coded to the four possible combinations of two boolean arguments. The header used when printing the truth table was hard-coded. Finally the macro that supported the defintion of a logical expresion in infix notation was limited to two arguments as well.

Possible input values

We want to create all possible ordered sets that can be created out of the n sets of input parameters for each logical variable. For two boolean parameters (that's what we had so far) it looks like this:

        +                             
        |  true         false         
+------------------------------------+
  true  | [true true]   [true false]  
        |                             
  false | [false true]  [false false] 
        +                             

I initially thought of this problem as a for comprehension in the form of

(for [x [true false] y [true false]] [x y])

To make that work for n arguments I would have to implement another macro to create a for comprehension with n generators. When I realised that the operation here is just an n-fold Cartesian product, I knew that this was not necessary. I decided to use clojure.math.combinatorics which was already a dependency of the project to calculate the Cartesian product of n sets of Boolean parameters instead.

Generating functions with a given arity

I had introduced the 'i' macro to have a simple and elegant way to express that its argument was to be interpreted as a logical expression in infix notation.

(i (a or b))

To support n logical variables we now need to move away from this succinct syntax a bit and specify the logical variables in use in a separate argument.

(i [a b c] (a and (b or c)))

Implementing this was way easier than I thought. It looks similar to this:

(defmacro [bindings & expr]
   `(fn ~bindings (infix ~expr)))
I also noticed that the deep code walking and code replacement I introduced last time, was completely unnecessary. I thought you need generated symbols, but that is only true if you want to use let inside a syntax quote, which I did not. I had probably stumbled over Clojure's quoting rules, which are one of the more complicated bits of the language.

This new argument was interesting in another respect: I wanted to use it to create a header for the truth table. But wanted to avoid this duplication:

(table [a b] (i [a b] (a or b)))

Extracting metadata from a function

A possible solution: Clojure functions have metadata about their arity which is exactly what we want and need to generate the header of the truth table. But the metadata is only present on functions created via defn. The one used here was anonymous. In addition you should be able to do
(table and)

That is not even a function. As we already know 'and' is a macro in Clojure but it has the necessary metadata. Even more than we need:

(:arglists (meta #'and))
([] [x] [x & next])

The hash-quote is a reader macro that translates to (var and) which resolves to the var object (as opposed to it's value) where the metadata is stored. The problem here: 'and' has more than one argument list and the relevant one in this context contains a var arg.

I ended up offering both APIs:

(table '[a b] and)
(table (i [a b] (a and b)))

The second variant uses the metadata to infer the header of the truth table while it's explicit in the first variant. I'm not entirely happy with that result as it seems a bit brittle: in the second variant it just uses the first argument list and falls flat on its face when the argument does not contain any metadata, which could well happen if you just specify an anonymous function yourself instead of using the 'i' macro.

Have a look at the complete code here on Github.

Read more about this series.

Tuesday, August 12, 2014

99 Clojure Problems – 47: Truth Tables for Logical Expressions (2)

"Continue problem P46 by defining and/2, or/2, etc as being operators. This allows to write the logical expression in the more natural way, as in the example: A and (A or not B). Define operator precedence as usual; i.e. as in Java."

If we want to have this 'natural way' of writing logical expressions we will have to introduce infix notation into Clojure's prefix world.

Example

ninety-nine-clojure.logic> (table (i (a and (a or not b))))

|    :a |    :b | :result |
|-------+-------+---------|
|  true |  true |    true |
|  true | false |    true |
| false |  true |   false |
| false | false |   false |
nil

Discussion

How do we get the desired syntax?

If you have read the previous article you know that we are deep in macro-land and there is no way back. This can be seen as a macro anti-pattern (See "Macros all the way down" in Clojure for the Brave and True).

We are already in a situation where our truth table function can only be a macro because we want to pass in unquoted macros as parameters. This is also true for the infix problem: What we need in a first step is a macro that allows us to write something like this:

(table #(infix (%1 and (%1 or not %2))))

Remember the truth table macro expects expressions that take two arguments. A first step towards that goal is to create an anonymous function with two arguments (%1, %2) and process our logical expression with a yet to write infix function or macro to turn it back into Clojure code. The infix notation is not easy to read due to the numbered arguments but we will work on that later.

Infix in Clojure

It is a well established exercise to implement infix operators in a Lisp. There is the exercise 2.58 in SICP for example that teaches us about the benefits of prefix notation over infix notation. The chapter 1.22 in the "Joy of Clojure" shows us in a similar fashion how we can avoid all the troubles in Clojure that usually come with the rules of operator precedence and still have some infix notation if we want it.

Now to get a basic infix notation we just need a rather simple macro that puts the operator into function position and adds parens around it.

([a op b]
     `(~op (infix ~a) (infix ~b)))
It recursively calls itself on the symbols 'a' and 'b', which can be composite expressions in parens like:
(a and b) 
or a simple boolean value. I came up with this to deal with both cases:
 ([x] (if (seq? x)
         `(infix ~@x)
         x))
It says: If the argument is a sub-expression in list form and therefore sequential apply the infix macro again otherwise return the value.

We have got all the binary operators covered assuming that they all have the same precedence. (Which they don't e.g. in Java which was mentioned in the original Prolog problem description). A bit trickier are now the unary operators like 'not'. If we use parens as in '(not a) and b)' it will work out of the box, as this negation of 'a' is already valid Clojure. I am supporting expressions like 'a and not b' with the following extension of my infix macro:

([a b c d]
     (if (unary? a)
       `(~c (~a (infix ~b)) (infix ~d) )
       `(~b (infix ~a) (~c (infix ~d)))))

The basic idea here is to take advantage of Clojure's support for multi-arity functions/macros and deal with a unary operator before the second value/sub-expression by interpreting any call with four arguments in that way. Now this falls obviously down as soon as we have something like 'not a and not b'. We will have to cover that case seperately.

Optional noise reduction

I already mentioned that the usage of the infix macros in combination with the truth tables leaves room for improvement:

(table #(infix (%1 and (%1 or not %2))))

The numbered arguments of the anonymous function are a bit ugly. We would rather have something like this:

(table (i (a and (a or not b))))

We imagine that 'i' is the macro that triggers the infix magic and the rest is an easy to read logical expression. We imagine further that 'i' is a macro that transform our expression into a function of two arguments 'a' and 'b'. The result of the transformation would be the following piece of Clojure code:

(fn [a b] (and a (or a (not b))))

[Update: As it turns out the symbol replacement described below is unnecessary. Stay tuned for problem 48 for more detail on this.]

The problem with that idea: Clojure won't allow you to introduce new bindings in a syntax quote (`) that might capture existing variables. The gensym mechanism is there for you to generate unique symbols to be used in a macro that won't accidentally hijack existing variables.

A post on Fogus' blog about deep code walking macros lead me to this implementation:

(defmacro i
  [& args]  
  (let [a (gensym)
        b (gensym)
        code (clojure.walk/postwalk-replace {'a a 'b b} args)]
    `(fn [~a ~b] (infix ~@code))))

It has its limitations: you can only use 'a' and 'b' as variables, as they are hard-coded. I then uses a deep code walking function to replace the 'a's and 'b's with generated symbols, which will also be used to generate a wrapper function around the logical expressions.

That was not very hard, but there would be a bit more work involved to get rid of the limitations. We will look at that when we tackle the next problem which will require us to support logical expressions of arbitrary arity. The source for my complete solution is as always on Github.

Read more about this series.

Tuesday, August 05, 2014

99 Clojure Problems – 46: Truth Tables For Logical Expressions

Define functions and, or, nand, nor, xor, impl, and equ (for logical equivalence) which return true or false according to the result of their respective operations; e.g. (and A B) is true if and only if both A and B are true.

A logical expression in two variables can then be written in prefix notation, as in the following example: (and (or A B) (nand A B)).

Now, write a predicate table which prints the truth table of a given logical expression in two variables.

Example

ninety-nine-clojure.logic> (table impl)

|    :a |    :b | :result |
|-------+-------+---------|
|  true |  true |    true |
|  true | false |   false |
| false |  true |    true |
| false | false |    true |

Discussion

This problem has three parts: Implementing the logical expressions as functions. Implementing the truth table function and finally—and this is Clojure specific—thinking about how to deal with the built-in logical expressions 'and' and 'or'.

Logical expressions in Clojure

Once you have implemented 'and', 'or' and 'not' you can implement all other logical expressions in terms of these three "primitives". In Clojure 'and' and 'or' are macros. I don't want to give an introduction to macros here (I recommend having a look at the most excellent Joy of Clojure or Clojure for the Brave and True) But I will say that much: As Clojure's code is just data, macros allow you to transform that data before compilation into other code/data.

Bearing that in mind and trying to understand clojure.core/and we hope to get an idea how to implement the most basic logical expressions for this problem ourselves. This is how the 'and' macro is implemented in Clojure:

(defmacro and
  ([] true)
  ([x] x)
  ([x & next]
   `(let [and# ~x]
      (if and# (and ~@next) and#))))

Even without understanding every last detail of this macro definition, we can see that Clojure's 'and' transforms the and-expression into a recursive series of if-expressions.

Filling in concrete values and using macroexpand makes things a bit clearer:

ninety-nine-clojure.logic> (macroexpand '(and true false))
(let* [and__3941__auto__ true] 
  (if and__3941__auto__ 
     (clojure.core/and false) 
     and__3941__auto__))
Expanded to the first level, we see how the and-expression is now an 'if' inside a 'let'. A recursive call to 'and' for the second argument is still unexpanded. This should give us enough inspiration to implement simple 'and' and 'or' functions of our own.

But we can also reuse the existing control structures Clojure offers right away to build the higher level expressions for 'nand', 'nor', 'equ', 'impl' and 'xor'.

Creating a truth table

The next step is to build the table function. I cheated a bit and used Clojure's print-table, hard-coding the possible inputs for a function with two boolean arguments. Print-table takes a sequence of maps for each row. To get the desired effect I interleaved a descriptive header with the result of evaluating the logical expressions and turned that into a sorted map. But it should not be too hard to built a simple printing function yourself.

Make it work with the built-in expressions

Now this last part is only relevant if you were lazy, as I was, and reused the existing Clojure expressions for 'and' and 'or'. Try to create a truth table for them and you will get a response similar to the following:

(table and)
CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/and, compiling:(NO_SOURCE_PATH:1:1) 
Now we already know that 'and' is implemented as a macro. Unless we are quoting we can't use it as a value:
(table 'and)

If we want to provide an API where the user does not need to know whether the argument to our table function is a macro and therefore has to be quoted, we have to write a macro ourselves.

Now this is a bit tricky and took a while. The hardest bit was was a helper macro I created to evaluate the logical expression (possibly a macro) for all input values, even though this is shamelessly taken from an answer on stackoverflow. The helper wraps the macro in a function where it is eval'd after making it referable by quoting it like so (with exemplary values added for clarity):

(list 'and true false)
I called it evaluator:
(defmacro evaluator [expr]
  `(fn [& args#]
     (eval `(~'~expr ~@args#))))
It uses two levels of syntax-quoting (`). The first to allow the introduction of the args-symbol and the second to allow the unquote-splicing (~@args#) of the args vector in the quoted function call (~'~expr) which we are building inside our evaluator function.

This kind of complexity is in my experience the exception and I am not even sure if there is not an easier solution to my problem than the one I found. But given the fact that the argument to our function is already a macro, I don't see a solution avoiding macros. Please let me know if you think I'm wrong. In the meantime have a look at the source code.

Read more about this series.

Sunday, July 13, 2014

99 Clojure Problems: 41: A List Of Goldbach Compositions

"Given a range of integers by its lower and upper limit, print a list of all even numbers and their Goldbach composition."

Example

(print-goldbach (range 9 21))
10 = 3 + 7
12 = 5 + 7
14 = 3 + 11
16 = 3 + 13
18 = 5 + 13
20 = 3 + 17

"In most cases, if an even number is written as the sum of two prime numbers, one of them is very small. Very rarely, the primes are both bigger than, say, 50. Try to find out how many such cases there are in the range 2..3000.

Example (minimum value of 50 for the primes)":

(print-goldbach (range 2000) 50)
992 = 73 + 919
1382 = 61 + 1321
1856 = 67 + 1789
1928 = 61 + 1867

Discussion

A simple problem as we have already implemented all the bits that do most of the work. To create a list of Goldbach compositions we take the input range (note the range semantics in Clojure: the upper limit is exclusive) filter out the even numbers that are greater than 2 (as required by Goldbach's conjecture). We then map the Goldbach function over the range and apply the mimimum filter for the first prime in the results (see the second example above).

We format the result and println it, generating a new line for every Goldbach composition. Have a look at the source once you tried it yourself.

The interesting aspect of this problem is the use of doall, which we have to call at the very end. Why? The intermediate representation of the data is a lazy sequence. By mapping println over that sequence we declare that we want to trigger a side effect (the printing). But the effect does not occur, due to laziness, until we force it with doall.

Read more about this series.

Monday, July 07, 2014

99 Clojure Problems – 40: Goldbach's Conjecture

Goldbach's conjecture says that every positive even number greater than 2 is the sum of two prime numbers. Example: 28 = 5 + 23. It is one of the most famous facts in number theory that has not been proved to be correct in the general case. It has been numerically confirmed up to very large numbers. Write a predicate to find the two prime numbers that sum up to a given even integer.

Test/Example


(deftest p40-goldbach
  (is (= [5 23] (goldbach 28))))

(def even-nats-greater-two (gen/such-that #(< 2 %) (gen/fmap #(* 2 %) gen/nat)))


(defspec goldbach-conjecture
  100
  (prop/for-all [i even-nats-greater-two]
                (let [res (goldbach i)]
                  (and
                   (= 2 (count res))
                   (every? prime? res)
                   (= i (reduce + res))))))

Discussion

A naive approach just looks at all prime numbers below the input value. We are then only interested in those primes that if subtracted from that input leave us with another prime number. Both numbers obtained by that method form the result. We already got a list of prime numbers, Clojure's take-while and filter do the rest. I expressed the fact that Goldbach's conjecture is only defined for even natural numbers greater than two with a precondition.

If you have been following this series you might have noticed that the example I give in the blog posts is almost always a unit test. I think this a quite succinct way to illustrate the intended behaviour of a function. But this time you will have noticed that there is something else.

I have added a dependency to clojure.test.check. Test.check is a QuickCheck inspired property-based testing library for Clojure. You can learn more about QuickCheck by having a look at the original paper.

Looking at the code above you will notice that a generative test consists of two parts. First a property (within the defspec). In this case I specified that for all even natural numbers greater than two the Goldbach function should return two prime numbers whose sum is equal to the input value. This property is an almost literal translation of Goldbach's conjecture.

Secondly you need to specify how to generate all possible input values that the test runner should use. Again: Instead of doing this explicitly for every single input value, as you would have to in a traditional exemplary unit test, you just define a generator. I used the built-in generator for natural numbers called nat. But in order to create only valid input values for the Goldbach function the generated values need to be greater than two and even. You can achieve this by using combinators on the original generator. A fmap * 2 shifts the domain of the generator into the even values. I then used the such-that combinator to filter out everything below two.

While writing these generative tests seems like more work at first sight you get back a more thorough verification of your program in return.

Property-based testing recognises the impossibility of coming up with test inputs that expose all edge cases. Instead it encourages you to define properties of your function that you expect to hold. The flip side of the coin is that property based tests won't contribute as much to the design of your APIs and your system as the traditional TDD approach did. But it is a very valuable attempt at automated verification.

Read more about this series.