Stumped with functional breadth-first tree traversal in Clojure? - algorithm

Say I have a tree defined as per the recommendation in this post, although it's a vector in my case, which hopefully shouldn't matter (they're vectors in Programming Clojure book):
(def tree [1 [[2 [4] [5]] [3 [6]]]])
which should be something like:
1
/ \
2 3
/ \ |
4 5 6
Now, I'd like to do a breadth-first traversal of the tree without any of the traditional means such as the queue, and instead use exclusively the stack to pass information around. I know this isn't the easiest route, but I'm doing it mostly as exercise. Also at this point I'm not planning to return a collection (I'll figure that out afterwards as exercise) but instead just print out the nodes as I travel through them.
My current solution (just starting out with Clojure, be nice):
(defn breadth-recur
[queue]
(if (empty? queue)
(println "Done!")
(let [collections (first (filter coll? queue))]
(do
; print out nodes on the current level, they will not be wrapped'
; in a [] vector and thus coll? will return false
(doseq [node queue] (if (not (coll? node)) (println node)))
(recur (reduce conj (first collections) (rest collections)))))))
The last line is not working as intended and I'm stumped about how to fix it. I know exactly what I want: I need to peel each layer of vectors and then concatenate the results to pass into recur.
The issue I'm seeing is mostly a:
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long
Basically conj doesn't like appending a vector to a long, and if I swap conj for concat, then I fail when one of the two items I'm concatenating isn't a vector. Both conj and concat fail when facing:
[2 [4] [5] [3 [6]]]
I feel like I'm missing a really basic operation here that would work both on vectors and primitives in both positions.
Any suggestions?
Edit 1:
The tree should actually be (thanks Joost!):
(def tree [1 [2 [4] [5]] [3 [6]]])
However we still haven't found a breadth-first solution.

Since apparently there is still no breadth-first solution posted, here is a simple algorithm, implemented first eagerly, and then transformed to be lazy:
(defn bfs-eager [tree]
(loop [ret [], queue (conj clojure.lang.PersistentQueue/EMPTY tree)]
(if (seq queue)
(let [[node & children] (peek queue)]
(recur (conj ret node) (into (pop queue) children)))
ret)))
(defn bfs-lazy [tree]
((fn step [queue]
(lazy-seq
(when (seq queue)
(let [[node & children] (peek queue)]
(cons node
(step (into (pop queue) children)))))))
(conj clojure.lang.PersistentQueue/EMPTY tree)))

Your tree data is incorrect. It should be [1 [2 [4] [5]] [3 [6]]]
Also, you're mixing the tree traversal with printing and building up a result. Things get simpler if you concentrate on doing the hard part separately:
(def tree [1 [2 [4] [5]] [3 [6]]])
NOTE THIS IS DEPTH-FIRST. SEE BELOW
(defn bf "return elements in tree, breath-first"
[[el left right]] ;; a tree is a seq of one element,
;; followed by left and right child trees
(if el
(concat [el] (bf left) (bf right))))
(bf tree)
=> (1 2 4 5 3 6)
CORRECT VERSION
(defn bf [& roots]
(if (seq roots)
(concat (map first roots) ;; values in roots
(apply bf (mapcat rest roots))))) ;; recursively for children
(bf tree)
=> (1 2 3 4 5 6)

This might help, I was creating an algorithm to evaluate if a tree is symmetric and used a breadth-first traversal:
(defn node-values [nodes]
(map first nodes))
(defn node-children [nodes]
(mapcat next nodes))
(defn depth-traversal [nodes]
(if (not (empty? nodes))
(cons (node-values nodes) (depth-traversal (node-children nodes)))))
(defn tree-symmetric? [tree]
(every?
(fn [depth] (= depth (reverse depth)))
(depth-traversal (list tree))))
(def tree '(1 (2 (3) (4)) (2 (4) (3))))
(node-values (list tree)) ; (1)
(node-children (list tree)) ; ((2 (3) (4)) (2 (4) (3)))
(depth-traversal (list tree)) ; ((1) (2 2) (3 4 4 3))
(tree-symmetric? tree) ; true

many combinations of reduceand conj can be replaced with single into call
in the case above with reduce you may need to pass an initial empty vector to reduce to
get make conjunction happy.

Related

How to represent the following data structure in scheme r5rs

In Python the data structure looks like this: [([1 2 3], [8 9 10])] (a list of tuple, where tuple is of size 2, and each tuple element is a list again)
How would I represent the same in Scheme r5rs?
This is what I tried: (list (cons `(1 2 3) `(8 9 10)))
But running (display (list (cons `(1 2 3) `(8 9 10)))) gives (((1 2 3) 8 9 10)) whereas I want (((1 2 3) (8 9 10)))
Edit
Using only lists (as per #Will Ness answer here):
(list ; a pair of elements,
(list 1 2 3) ; 1 each is itself
(list 8 9 10))) ; 2 a list
works.
And I can access the 2nd element of the tuple by
(cadr (car x)) which gives (8 9 10) (which is correct)
I was just thinking how would I build this up using cons since my tuple will only contain 2 elements and from what I know cons are used to represent a pair in Scheme. Any ideas on how to do this using cons?
[([1 2 3], [8 9 10])] (a list of tuple, where tuple is of size 2, and each tuple element is a list again)
(list ; a list of
(list ; a pair of elements,
(list 1 2 3) ; 1 each is itself
(list 8 9 10))) ; 2 a list
Scheme is untyped, so we can just use lists for tuples. It is simpler that way -- the access is uniform. The first is car, the second cadr.
Your way is correct as well. What really determines whether it is or not is how you can access your data to retrieve its constituents back. And with your way you can indeed, too: the first element will be car and the second -- cdr.
(update to the question edit:) whether you use (cons 1 (cons 2 '())) or (list 1 2) is immaterial. the resulting structure in memory is the same.
There is an infinity of ways to represent data. You have been presented a way. Here is other way:
(define mk/data
(lambda (a b)
(lambda (?)
(cond ((eq? ? 'repr) (list (list a b)))
((eq? ? 'first) a)
((eq? ? 'second) b)))))
(define data/test (mk/data '(1 2 3) '(8 9 10)))
(data/test 'repr)
(data/test 'first)
(data/test 'second)
This is another way how the big systems actually represent data.

Reversing list with sublists and atoms in lisp

I am new to a functional programming and trying to reverse a list in lisp. List consists of sublists and atoms. The function (reverse-tree '((1 2) 5 6 (3))) should return ((3) 6 5 (2 1)). Here is my function:
(define (reverse-tree s)
;; giving problem with an atom
(if (not(list? s)) ( reverse-tree s) (reverse (map reverse s)))
)
It works when I do (reverse-tree '((1 2) (3))) => ((3) (2 1)). But it crashes when I do (reverse-tree '((1 2) 5 6 (3))). The error I am getting is reverse: contract violation expected: list?
I am limited to use only: reverse, map, if, cond, list? null? functions.
EDIT, someone marked this question as duplicate, but there is a restriction in this problem, which is not similar to the other question. I cannot use cons, car, cdr, append. Any suggestions?
Think about the problem in pieces. First, if the function is given a list as an argument, you need to reverse that list. That's easy, something like:
(define (reverse-tree tree)
(if (list? tree)
(reverse tree)
...))
But you also need to reverse all sublists in it and all sublists in them and so on. Since that's exactly what our reverse-tree does, we should use map to apply it to all elements in the reversed list (it doesn't actually matter whether you use map before or after reversing the list):
(define (reverse-tree tree)
(if (list? tree)
(map reverse-tree (reverse tree))
...))
But if the input is ((1 2) 3 4 (5 6)), the map will call reverse-tree on the atoms 3 and 4 too. It wouldn't make any sense to reverse them, so we can just return them:
(define (reverse-tree tree)
(if (list? tree)
(map reverse-tree (reverse tree))
tree))
Now it should work:
(reverse-tree '((1 2) 3 4 (5 6)))
;=> ((6 5) 4 3 (2 1))
(reverse-tree '((1 2) 3 4 (5 6 (7 8))))
;=> (((8 7) 6 5) 4 3 (2 1))

List processing in clojure, tail recursion needed

Given a sorted list of intervals, e.g.
(def lst (list [7 10] [32 35]))
I need to implement a function that adds a new interval to the list. If the new interval is adjacent to any of those from the list, they should be merged:
(= (add-range [1 3] lst) (list [1 3] [7 10] [32 35])) ;; prepend left
(= (add-range [1 6] lst) (list [1 10] [32 35])) ;; merge left
(= (add-range [11 20] lst) (list [7 20] [32 35])) ;; merge right
(= (add-range [11 31] lst) (list [7 35])) ;; merge left and right
This is my implementation:
(defn add-range
[range range-list]
(if (empty? range-list)
(list range)
(let
[lo (first range)
hi (second range)
head (first range-list)
head-lo (dec (first head))
head-hi (inc (second head))]
(if (< hi head-lo)
(cons range range-list)
(if (= hi head-lo)
(cons [lo (second head)] (rest range-list))
(if (= lo head-hi)
(recur [(first head) hi] (rest range-list))
(cons head (add-range range (rest range-list)))))))))
It works and looks quite elegant too, but the last line contains a recursive call add-range which can not be replaced with recur because it is not the last call. I'm planning to have long range lists in my application and I don't want to blow up the stack.
How this can be rewritten using the tail recursion?
Is there another approach to solve the problem? Lazy sequences maybe?
UPDATE
The sorted list is actually not required. This can be a set or even an unsorted list, but it would be really nice to do it in a single pass.
Using a sorted set you can implement it as:
;; first the constructor
(defn ranges [& rs]
(apply sorted-set-by
(fn [[from-a to-a] [from-b to-b]]
(< to-a (dec from-b))) rs))
;; then add-range itself
(defn add-range [ranges [from to :as r]]
(let [rs (subseq ranges <= [from from] <= [to to])
ranges (reduce disj ranges rs)]
(conj ranges
(let [[from'] (or (first rs) r)
[_ to'] (or (last rs) r)]
[(min from from') (max to to')]))))
Let's try your tests:
=> (def lst (ranges [7 10] [32 35]))
#'user/lst
=> (add-range lst [1 3])
#{[1 3] [7 10] [32 35]}
=> (add-range lst [1 6])
#{[7 10] [32 35]}
=> (add-range lst [11 20])
#{[7 20] [32 35]}
=> (add-range lst [11 35])
#{[7 35]}
Addendum #1: add-range is O((m + 1) log n) where n is the size of the ranges set and m the number of merged intervals.
In my experience making something tail recursive involves passing as arguments all local state. Looking at the algo, it looks like already processed range items is the local state. ie, final result = (ranges ignored + merged-range + ranges not required to be considered).
Consider the following version, it explicitly passes a seq of already processed items.
(defn add-range
[range-obj ranges]
(loop [processed []
range-obj range-obj
remaining (list* ranges)]
(if (empty? remaining)
(conj processed range-obj)
(let [[lo hi] range-obj
[h-lo h-hi :as head] (first remaining)
upper-merge-threshold (dec h-lo)
lower-merge-threshold (inc h-hi)]
(cond
(< hi upper-merge-threshold) (into processed
(conj remaining range-obj))
(= hi upper-merge-threshold) (into processed
(conj (rest remaining) [lo h-hi]))
(= lo lower-merge-threshold) (recur processed
[h-lo hi]
(rest remaining))
:else (recur (conj processed head)
range-obj
(rest remaining)))))))
My version accepts a vector and returns a vector. You could modify the relevant code to make it accept a list and return a list.
As for is there a better algorithm, I don't know. I have simply converted your algo to be tail recursive.

`conj` and `disj` for lists in clojure? Possible other data structures to use for this? Contains SCCEE

For a class project I am implementing the Bron-Kerbosch algorithm for finding maximal cliques in a graph. With help from others on SO I have gotten down to the final few issues.
This link (http://pastebin.com/2GUPZFnR) contains a SSCCE of my current implementation that outlines the issue. The issue I think lies with my use of disj to find the intersection of two lists. I think this based on the error given when I call BK-Call with the "sanity" input.
fptests.core> (BK-Call (sanity1))
ClassCastException clojure.lang.PersistentList$EmptyList cannot be cast to clojure.lang.IPersistentSet clojure.core/disj (core.clj:1449)
This error tracks down to a few lines in my Bron-Kerbosch function itself
(defn Bron-Kerbosch [r p x graph cliques]
(cond (and (empty? p) (empty? x)) (conj cliques r)
:else
(let [neigh (neighV graph (dec (count p)))]
(loop [loop-clq '(cliques)
loop-cnt '(dec (count p))
loop-p '(p)
loop-x '(x)]
(cond (= -1 loop-cnt) loop-clq
:else
(recur (conj loop-clq (Bron-Kerbosch (conj r loop-cnt) (conj p neigh) (disj x neigh)))
(dec loop-cnt)
(disj p loop-cnt)
(conj x loop-cnt)))))))
Specifically in the recursive call to the function in the recur form. Though this issue I think applies to all uses of conj and disj. It seems that conj "works" but not in the manner I assumed.
fptests.core> (disj '(1) '(1 2 3))
ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.IPersistentSet clojure.core/disj (core.clj:1449)
fptests.core> (conj '(1) '(2 3))
((2 3) 1)
I assumed that (conj '(1) '(2 3)) would return (1 2 3) and not (1 (2 3)). So it seems my use of lists in the function overall is the issue. Is there a way that I could overcome this issue?
I would have to imagine there are functions like conj and disj that work with lists. I guess my other option if this is not true is to use some other data structure in the algorithm. What would be appropriate?
use cons, rest and concat.
user=> (cons 1 '(2 3))
(1 2 3)
user=> (cons '(1) '(2 3))
((1) 2 3)
user=> (cons 1 ())
(1)
user=> (rest '(1 2 3))
(2 3)
user=> (concat '(1) '(2 3))
(1 2 3)
I would indeed suggest using a data structure more suited to the problem at hand, namely a set.
You're already using Clojure hash sets in your graph representation ((repeat n #{}) in empty-graph); the r, p and x parameters of the Bron-Kerbosch step function are all conceptually sets, so it makes sense to represent them as Clojure sets as well.
With that choice of representation, things will become simpler for you – set intersection can be computed using clojure.set/intersection, disj works for removing individual keys etc.
On a separate note, it would be more natural to use if rather than cond in Bron-Kerbosch (both conds in that function actually only have two branches). More importantly, you'll want to remove the quotes from the init expressions in your loop – '(dec (count p)) (notice the '), to take one example, is a two-element list, not a number. (It's also somewhat unusual in Clojure for function names to include capital letters, but of course this is purely a matter of style.)

Walking through a binary tree

I'm having issues writing a function to walk through a binary tree, the function takes in a search_term, list and returns true or false. Here is what I have and it's essentially the same thing I found googling how to implement binary search in Scheme.
(define (tree-lookup val tree)
(if (empty-tree? tree)
#f
(let ((curr-val (node-value tree))
(left (node-left tree))
(right (node-right tree)))
(cond ((equal? val curr-val) #t)
((< val curr-val))
(tree-lookup val left)
(else
(tree-lookup val right))))))
(define tree-test '(((1 2) 3)(4 (5 6)) 7 (8 9 10))) ; Test tree
The problem comes when it tries to compare the "val" variable with the node. This means I am comparing a real number to a list, like (< 2 '((1 2) 3)). I tried testing for atom values only but then I am stuck on how to go back up the tree when I reach a leaf.
Here's the error message:
<: contract violation
expected: real?
given: '{{1 2} 3}
argument position: 2nd
other arguments...:
8
At first glance the procedure looks fine. I suspect that the problem is in the node-value, node-left and node-right procedures, or in the way you're building the tree - for starters, the sample tree provided in the question doesn't seem right to me.
Think about it, the error message signals that the < operator was applied to the list '{{1 2} 3}, meaning that curr-val is a list, but it should be a value.

Resources