I was trying to implement an add function for the BST
(defn size
"Return the number of nodes in a BST."
[bst]
(cond (nil? bst) 0
:else (+ 1 (+ size(:left bst) size(:right bst)) ) )
)
Does this look right?
Couple of things wrong here. You are still calling functions in the "standard" way. size(:left bst) will raise an exception, you need (size (:left bst)) (paranthesis around are important as well as a space after name of the function).
Second thing - no need to use cond when you have one case and :else. Just use if:
(if (nil? bst)
0
(+ 1 (+ (size (:left bst)) (size (:right bst)))))
Related
I want to write a function to return the sum of all numbers divisible by 3 in a given list. I don't know how to pattern match on the size of a list. I get a nil pointer exception when I run the following code.
I am trying to do this using first principles, instead of using loop map and reduce
(defn sum3
[[head & tail]]
(if (= (mod head 3) 0)
(+ head (sum3 tail))
(sum3 tail))
[[head]]
(if (= (mod head 3) 0)
head
0))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println (sum3 [1 2 3])))
Function dispatch in clojure is done on the number of arguments to the function and not on the number of destructured values in the function call.
Once the appropriate arity has been selected, and the function has started running, the destructuring occurs and binds the symbols to the desctructured values.
Fortunatly clojure offers arbitrary custom function dispatch in the form of multimethods so if you want to dispatch based on the length of the arguments you can. For your example it's overkill though not particularly hard. There are other cases where it makes sense.
A normal, single arity, approach to this function would look like this:
user> (defn sum3
[[head & tail]]
(if (seq tail)
(if (= (mod head 3) 0)
(+ head (sum3 tail))
(sum3 tail))
(if (= (mod head 3) 0)
head
0)))
#'user/sum3
user> (sum3 [1 2 3 4 5 6])
9
You should in general always use recur rather than direct recursion though for this question it's not too much of an issue when demonstrating this principal .
First let's do the version using reduce:
(defn sum3 [coll]
(reduce (fn [sum el]
(if (zero? (mod el 3))
(+ sum el)
sum)) 0 coll))
Notice the use of zero?. No need for pattern-matching here.
Then we can go on to use recursivity:
(defn sum3
([coll] (sum3 0 coll))
([sum [head & tail]]
(let [add (if (zero? (mod head 3))
(+ sum head)
sum)]
(if tail
(recur add tail)
add))))
Again, no pattern matching (you would have to use core.match for that -clojure does not use pattern matching). The dispatch is only made using the number of arguments. This is why your function was not valid syntax: it was in both cases a 1-arity function. Note the use of recur to recurse the function. It can only be used for tail-recursion.
We could make it a 1-arity function without dispatching on arguments as well:
(defn sum3
[[head & tail]]
(let [m3? (zero? (mod head 3))]
(if (seq tail)
(if m3?
(+ head (sum3 tail))
(sum3 tail))
(if m3? head 0))))
Note that this version is not tail-recursive and will overflow for big inputs.
But really the reduce version - or even the loop version look much better.
in fact the main error is in the defn syntax. You don't define two arities here, rather make one arity [[head]] and then goes the body, which is totally valid clojure code. To make 2 arities you should put each into brackets:
(defn sum3
([[head]]
(if (= (mod head 3) 0)
head
0))
([[head & tail]]
(if (= (mod head 3) 0)
(+ head (sum3 tail))
(sum3 tail))))
but it would also fail
because you don't define different arities, they are equal (one argument call), so the compiler would produce an error. Clojure destructuring is not pattern matching at all. It is just a way of retrieving items from a collection. But you can fix this (emulate kind of length pattern matching) with a minor change:
user>
(defn sum3
([head]
(if (= (mod head 3) 0)
head
0))
([head & tail]
(if (= (mod head 3) 0)
(+ head (apply sum3 tail))
(apply sum3 tail))))
#'user/sum3
user> (sum3 1 2 3 4 5 6)
9
user> (apply sum3 [1 2 3 4 5 6])
9
now you have fair variant with two different arities.
But yes, it is not tail recursive, so in real life you would go with reduce or loop/recur
I am having a hard time tracking down a stackoverflow error produced by my clojure implementation of the Bron-Kerbosch algorithm.
Below is my implementation of the algorithm itself, and here is a link to a SSCCE outlining the issue http://pastebin.com/gtpTT4B4.
(defn Bron-Kerbosch [r p x graph cliques]
;(println (str "R:" r " P:" p " X:" x " Clq:" cliques))
(cond (and (empty? p) (empty? x)) (concat 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 (concat loop-clq
(Bron-Kerbosch (concat r loop-cnt)
(concat p neigh)
(filter (set x) neigh)
graph cliques))
(dec loop-cnt)
(filter (set p) loop-cnt)
(concat x loop-cnt)))))))
I would have to assume that the issue obviously lies within one of my two bootstrap conditions (cond (and (empty? p) (empty? x)) and (cond (= -1 loop-cnt) because the function algorithm is recursive.
Though this assumes that I am building the lists x r p correctly. Judging by the output of the commented out print statement (cliques is always printed as an EmptyList) I assume that my list comprehension might also be the issue.
Along the same lines, the other issue I can somewhat see is that I am not actually calling the algorithm properly in the BK-Call function (in the SSCCEE).
My overall question is what is causing this? Though this is somewhat too open, another question that might lead me to my answer is how I might go about using the print statement on the first line.
When the print statement is uncommented it produces the output
R:clojure.lang.LazySeq#2044e0b9 P:clojure.lang.LazySeq#7f9700a5 X:clojure.lang.LazySeq#1 Clq:clojure.lang.PersistentList$EmptyList#1
I assume that if I could see that x r p are at each call I might be able to see where the algorithm is going wrong.
Can anyone point me in the right direction?
EDIT: The neighV function from the SSCCE
(defn neighV [graph nodenum]
(let [ret-list (for [i (range (count graph)) :when (contains? (graph i) nodenum)] i)]
ret-list))
EDIT2: Noisesmith's answers had gotten me closer to the solution and made sense to me. I wrapped all of my concat in doall. After trying to call the function again I was getting "Cannot cast Long to Seq" errors, I figured that these stemmed from trying to concat loop-cnt onto lists in the function
fptests.core> (BK-Call (sanity1))
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:505)
fptests.core> (concat 1 '(2 3))
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:505)
So I then wrapped each loop-cnt in a '() to turn it into a list before it is concat
fptests.core> (concat '(1) '(2 3))
(1 2 3)
Which, after I made all of these changes, I ended back at my stack overflow.. Here is the new Bron-Kerbosch function with all of the edits. I guess I now have the same questions as I did before..
Though the new ones are, did I implement that changes that I should have correctly, does the usage of '() make sense to fix the issue that came up after implementing noisesmith's changes?
(defn Bron-Kerbosch1 [r p x graph cliques]
(cond (and (empty? p) (empty? x)) (doall (concat 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 (doall (concat loop-clq
(Bron-Kerbosch1 (doall (concat r '(loop-cnt)))
(doall (concat p neigh))
(filter (set x) neigh)
graph cliques)))
(dec loop-cnt)
(filter (set p) '(loop-cnt))
(doall (concat x '(loop-cnt)))))))))
EDIT3: After patiently waiting for my prn statements to stop (not sure why I put them in when I knew it was in a SO) I found that most if not all statements printed were along the lines of
"R:" (loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt ...)
"P:" (range (count graph) 0 2 3) " X:" () " Clq:" ()
After inspecting this some I realized that I have not been recursively calling the function properly. I have been union'ing items to P instead of removing them. This causes P to continuously grow. This is most likely the cause of my stack overflow. Though there are still some issues. I still am creating a stackoverflow, yet again.
Once I fixed my issue of continuing to union to P my issue is that when I concat loop-cnt it is not, I guess to say, evaluated to a value but it stays as a variable name loop-cnt. I suspect that my stack overflow now lies with my bootstrap condition not being met because it cannot be met if loop-cnt is not evaluated to a number.
So I think my issue now lies with concat loop-cnt to a list as a number and not a variable.
concat is lazy. Recursive calls that build concat on top of concat, without realizing any of the prior layers of laziness, each add to the size of the stack of calls that will be needed to realize the lazy-seq.
Does this concatenation need to be lazy at all? If not, wrap the calls to concat in calls to doall. This will make the concatenation eager, which reduces the size of the call stack needed to realize the final result, and thus eliminating the StackOverflowError.
Also, the correct way to print a lazy-seq and see the contents is prn, you can use pr-str to get the form of the value that pr or prn would use as a string, if needed.
You are misusing quoted lists, I think.
For example, in (defn Bron-Kerbosch1 [ ... ] ... ), '(cliques) evaluates to a list containing the symbol cliques, not to a list containing the argument cliques as its one element. You want (list cliques) for that.
Similar cases abound.
I'm trying to implement deep-reverse in clojure. If lst is (1 (2 (3 4 5)) (2 3)), it should return ((3 2) ((5 4 3) 2) 1). This is what I have so far:
defn dRev [lst]
( if (= lst ())
nil
( if (list? (first lst))
( dRev (first lst) )
( concat
( dRev (rest lst)) (list (first lst))
)
)
)
)
However, my implementation only works if the nested list is the last element, but the resulted list is also flattened.
For eg: (dRev '(1 2 (3 4)) will return (4 3 2 1).
Otherwise, for eg: (dRev '(1 (2 3) 4)) will return (3 2 1) only.
I hit this brick wall for a while now, and I can't find out the problem with my code. Can anyone please help me out?
The other answer gave you the best possible implementation of a deep-reverse in Clojure, because it uses the clojure.walk/postwalk function which generalizes the problem of deep-applying a function to every element of a collection. Here I will instead walk you through the problems of the implementation you posted.
First, the unusual formatting makes it hard to spot what's going on. Here's the same just with fixed formatting:
(defn dRev [lst]
(if (= lst ())
nil
(if (list? (first lst))
(dRev (first lst))
(concat (dRev (rest lst))
(list (first lst))))))
Next, some other small fixes that don't yet fix the behaviour:
change the function name to conform to Clojure conventions (hyphenation instead of camel-case),
use the usual Clojure default name for collection parameters coll instead of lst,
use empty? to check for an empty collection,
return () in the default case because we know we want to return a list instead of some other kind of seq,
and use coll? instead list? because we can just as well reverse any collection instead of just lists:
(If you really want to reverse only lists and leave all other collections as is, reverse the last change.)
(defn d-rev [coll]
(if (empty? coll)
()
(if (coll? (first coll))
(d-rev (first coll))
(concat (d-rev (rest coll))
(list (first coll))))))
Now, the formatting fix makes it obvious what's the main problem with your implementation: in your recursive call ((d-rev (first coll)) resp. (dRev (first lst))), you return only the result of that recursion, but you forget to handle the rest of the list. Basically, what you need to do is handle the rest of the collection always the same and only change how you handle the first element based on whether that first element is a list resp. collection or not:
(defn d-rev [coll]
(if (empty? coll)
()
(concat (d-rev (rest coll))
(list (if (coll? (first coll))
(d-rev (first coll))
(first coll))))))
This is a working solution.
It is terribly inefficient though, because the concat completely rebuilds the list for every element. You can get a much better result by using a tail-recursive algorithm which is quite trivial to do (because it's natural for tail-recursion over a sequence to reverse the order of elements):
(defn d-rev [coll]
(loop [coll coll, acc ()]
(if (empty? coll)
acc
(recur (rest coll)
(cons (if (coll? (first coll))
(d-rev (first coll))
(first coll))
acc)))))
As one final suggestion, here's a solution that's halfways towards the one from the other answer by also solving the problem on a higher level, but it uses only the core functions reverse and map that applies a function to every element of sequence but doesn't deep-recurse by itself:
(defn deep-reverse [coll]
(reverse (map #(if (coll? %) (deep-reverse %) %) coll)))
You can build what you are writing with clojure.walk/postwalk and clojure.core/reverse. This does a depth-first traversal of your tree input and reverses any seq that it finds.
(defn dRev [lst]
(clojure.walk/postwalk #(if (seq? %) (reverse %) %) lst))
Here is my version of the problem, if you enter something like this:
(deep-reverse '(a (b c d) 3))
It returns
=> '(3 (d c b) a)
The problem is taken from Ninety-Nine Lisp Problems
My code ended up like this, though, they might be better implementations, this one works fine.
(defn deep-reverse
"Returns the given list in reverse order. Works with nested lists."
[lst]
(cond
(empty? (rest lst)) lst
(list? (first lst)) (deep-reverse(cons (deep-reverse (first lst)) (deep-reverse (rest lst))))
:else
(concat (deep-reverse (rest lst)) (list (first lst)))))
Hope this is what you were looking for!
I have an ANTLR3 AST which I need to traverse using a post-order, depth-first traversal which I have implemented as roughly the following Clojure:
(defn walk-tree [^CommonTree node]
(if (zero? (.getChildCount node))
(read-string (.getText node))
(execute-node
(map-action node)
(map walk-tree (.getChildren node)))))))
I would like to convert this to tail recursion using loop...recur, but I haven't been able to figure out how to effectively use an explicit stack to do this since I need a post-order traversal.
Instead of producing a tail recursive solution which traverses the tree and visits each node, you could produce a lazy sequence of the depth first traversal using the tree-seq function and then get the text out of each object in the traversal. Lazy sequences never blow the stack because they store all the state required to produce the next item in the sequence in the heap. They are very often used instead of recursive solutions like this where loop and recur are more diffacult.
I don't know what your tree looks like though a typical answer would look something like this. You would need to play with the "Has Children" "list of children" functions
(map #(.getText %) ;; Has Children? List of Children Input Tree
(tree-seq #(> (.getChildCount #) 0) #(.getChildren %) my-antlr-ast))
If tree-seq does not suit your needs there are other ways to produce a lazy sequence from a tree. Look at the zipper library next.
As you mention, the only way to implement this using tail recursion is to switch to using an explicit stack. One possible approach is to convert the tree structure into a stack structure that is essentially a Reverse Polish notation representation of the tree (using a loop and an intermediate stack to accomplish this). You would then use another loop to traverse the stack and build up your result.
Here's a sample program that I wrote to accomplish this, using the Java code at postorder using tail recursion as an inspiration.
(def op-map {'+ +, '- -, '* *, '/ /})
;; Convert the tree to a linear, postfix notation stack
(defn build-traversal [tree]
(loop [stack [tree] traversal []]
(if (empty? stack)
traversal
(let [e (peek stack)
s (pop stack)]
(if (seq? e)
(recur (into s (rest e))
(conj traversal {:op (first e) :count (count (rest e))}))
(recur s (conj traversal {:arg e})))))))
;; Pop the last n items off the stack, returning a vector with the remaining
;; stack and a list of the last n items in the order they were added to
;; the stack
(defn pop-n [stack n]
(loop [i n s stack t '()]
(if (= i 0)
[s t]
(recur (dec i) (pop s) (conj t (peek s))))))
;; Evaluate the operations in a depth-first manner, using a temporary stack
;; to hold intermediate results.
(defn eval-traversal [traversal]
(loop [op-stack traversal arg-stack []]
(if (empty? op-stack)
(peek arg-stack)
(let [o (peek op-stack)
s (pop op-stack)]
(if-let [a (:arg o)]
(recur s (conj arg-stack a))
(let [[args op-args] (pop-n arg-stack (:count o))]
(recur s (conj args (apply (op-map (:op o)) op-args)))))))))
(defn eval-tree [tree] (-> tree build-traversal eval-traversal))
You can call it as such:
user> (def t '(* (+ 1 2) (- 4 1 2) (/ 6 3)))
#'user/t
user> (eval-tree t)
6
I leave it as an exercise to the reader to convert this to work with a Antlr AST structure ;)
I'm not skilled up on clojure, but I think I understand what you're looking for.
Here's some pseudocode. The stack here in my pseudocode looks like a stateful object, but it's quite feasible to use an immutable one instead. It uses something like O(depth of tree * max children per node) heap.
walk_tree(TreeNode node) {
stack = new Stack<Pair<TreeNode, Boolean>>();
push(Pair(node, True), stack)
walk_tree_aux(stack);
}
walk_tree_aux(Stack<Pair<TreeNode, Boolean>> stack) { -- this should be tail-recursive
if stack is empty, return;
let (topnode, topflag) = pop(stack);
if (topflag is true) {
push Pair(topnode, False) onto stack);
for each child of topnode, in reverse order:
push(Pair(child, True)) onto stack
walk_tree_aux(stack);
} else { -- topflag is false
process(topnode)
walk_tree_aux(stack);
}
}
I'm learning Clojure, and I'm trying to solve the Problem 31: Write a function which packs consecutive duplicates into sub-lists.
(= (__ [1 1 2 1 1 1 3 3]) '((1 1) (2) (1 1 1) (3 3)))
I know I can solve this using identity, and in a functional way, but I want to solve it using recursion, because I've not well established this idea in my brain.
My solution would be this:
(defn packing [lista]
(loop [[fst snd :as all] lista mem [] tmp '(fst)]
(print "all is " all "\n\n") ;; something is wrong; it always is an empty list
(if (seq? all)
(if (= fst snd)
(recur (rest all) mem (cons snd tmp))
(recur (rest all) (conj mem tmp) (list snd)))
(seq mem))))
My idea is a recursive loop always taking the first 2 items and comparing. If they are the same number, I include this inside a temporary list tmp; if they're different, I include my temporary list inside men. (This is my final list; a better name would be final_list.)
Because it compares the first 2 items, but at the same time it needs a recursive loop only bypassing the first item, I named the entire list all.
I don't know if the logic is good but inclusive if this was wrong I'm not sure why when I print.
(print "all is " all "\n\n") I receive an empty list
A few points:
'(fst) creates a list containing a symbol fst, not the value of fst, this is one of the reasons to prefer using vectors, e.g., [fst]
you should avoid assuming the input will not be empty
you can use conj for both lists and vectors
destructuring is nestable
(defn packing [coll]
(loop [[x & [y :as more] :as all] coll
result []
same '()]
(if all
(if (= x y)
(recur more result (conj same x))
(recur more (conj result (conj same x)) '()))
result)))
in your code all isn't empty..only happen than is an infinite loop and you always see a empty list...in the firsts lines you can see than it works like expected..
the mistake is in (seq? all) because a empty list is a seq too... try (seq? '()) and return true...then you do a empty loop
you need change this for (empty? all) your code would be
other mistake is '(fst) because it return the simbol fst and not the value...change it for (list fst)
(defn badpacking [lista]
(loop [[fst snd :as all] lista mem [] tmp (list fst)]
(if (empty? all)
(seq mem)
(if (= fst snd)
(recur (rest all) mem (cons snd tmp))
(recur (rest all) (conj mem tmp) (list snd))))))