Mutation Problem - Clojure - list

having trouble changing an element of my function represented as a list.
code for random function:
(defn makerandomtree-10
[pc maxdepth maxwidth fpx ppx]
(if-let [output
(if (and (< (rand) fpx) (> maxdepth 0))
(let [head (nth operations (rand-int (count operations)))
children (doall (loop[function (list)
width maxwidth]
(if (pos? width)
(recur (concat function
(list (makerandomtree-10 pc (dec maxdepth)
(+ 2 (rand-int (- maxwidth 1))) fpx ppx)))
(dec width))
function)))]
(concat (list head) children))
(if (and (< (rand) ppx) (>= pc 0))
(nth parameters (rand-int (count parameters)))
(rand-int 100)))]
output
))
I will provide also a mutation function, which is still not good enough. I need to be able to eval my statement, so the following is still insufficient.
(defn mutate-5
"chooses a node changes that"
[function pc maxwidth pchange]
(if (< (rand) pchange)
(let [output (makerandomtree-10 pc 3 maxwidth 0.5 0.6)]
(if (seq? output) output (list output)))
;mutate the children of root
;declare an empty accumulator list, with root as its head
(let [head (list (first function))
children (loop [acc(list)
walker (next function)] (println "----------") (println walker) (println "-----ACC-----") (println acc)
(if (not walker)
acc
(if (or (seq? (first function)) (contains? (set operations) (first function)))
(recur (concat acc (mutate-5 walker pc maxwidth pchange))
(next walker))
(if (< (rand) pchange)
(if (some (set parameters) walker)
(recur (concat acc (list (nth parameters (rand-int (count parameters)))))
(if (seq? walker) (next walker) nil))
(recur (concat acc (list (rand-int 100)))
(if (seq? walker) (next walker) nil)))
(recur acc (if (seq? walker) (next walker) nil))))
))]
(concat head (list children)))))
(side note: do you have any links/books for learning clojure?)

Check out the clojure.walk namespace. It's likely that a function like clojure.walk/postwalk-replace is what you're looking for.

Related

How to rewrite this function to be tail-recursive?

I'm reading the book The Little Schemer, I implement the functions in Clojure, How to rewrite this function as a tail-recursive function in Clojure?
(defn rember*
[a lat]
(cond
(empty? lat) []
(clojure.inspector/atom? (first lat))
(if (= a (first lat))
(rember* a (rest lat))
(cons (first lat)
(rember* a (rest lat))))
:else
(cons (rember* a (first lat))
(rember* a (rest lat)))))
Here is a translation of your code to a version that uses a loop and two lists instead of recursion in order to maintain program state:
(defn rember* [a lat]
(loop [[[op-type a lat] & rest-ops] (list [:rember a lat])
data '()]
(case op-type
nil (first data)
:value (recur rest-ops (cons a data))
:rember (cond
(empty? lat) (recur rest-ops (cons '() data))
(clojure.inspector/atom? (first lat))
(if (= a (first lat))
(recur (cons [:rember a (rest lat)] rest-ops) data)
(recur (into rest-ops [[:cons]
[:rember a (rest lat)]
[:value (first lat)]])
data))
:else (recur (into rest-ops [[:cons]
[:rember a (rest lat)]
[:rember a (first lat)]])
data))
:cons (let [[a b & data] data]
(recur rest-ops (cons (cons b a) data))))))
I agree, loop-recur is the more clojuresk answer!
But for a tail-recursive version, you could also do:
(def atom? (complement coll?))
(defn rember*
([a lat] (rember* a lat []))
([a lat acc]
(cond (empty? lat) (seq acc) ;; or just `acc` when result should be vector
(atom? (first lat)) (if (= a (first lat))
(rember* a (rest lat) acc)
(rember* a (rest lat) (conj acc (first lat))))
:else (rember* a (rest lat) (conj acc (rember* a (first lat)))))))
With this, you can easily build loop-recur by replacing the recursive function call using recur. However note that the last call of rember* cannot be placed by recur - because you cannot nest recur calls.
(defn rember* [a lat]
(loop [a a
lat lat
acc []]
(cond (empty? lat) (seq acc)
(atom? (first lat)) (if (= a (first lat))
(recur a (rest lat) acc)
(recur a (rest lat) (conj acc (first lat))))
:else (recur a (rest lat) (conj acc (rember* a (first lat)))))))

How to fix recursive search through list

I'm currently trying to learn Clojure. But I am having trouble creating a function that recursively searches through each element of the list and returns the number of "a"'s present in the list.
I have already figured out how to do it iteratively, but I am having trouble doing it recursively. I have tried changing "seq" with "empty?" but that hasn't worked either.
(defn recursive-a [& lst]
(if (seq lst)
(if (= (first lst) "a")
(+ 1 (recursive-a (pop (lst))))
(+ 0 (recursive-a (pop (lst)))))
0))
Welcome to stack overflow community.
You code is fine, except that you made a few minor mistakes.
Firstly, there is one extra pair of braces around your lst parameter that you forward to recursive function. In LISP languages, braces mean evaluation of function. So, first you should remove those.
Second thing is the & parameter syntactic sugar. You do not want to use that until you are certain how it affects your code.
With these changes, the code is as follows:
(defn recursive-a [lst]
(if (seq lst)
(if (= (first lst) "a")
(+ 1 (recursive-a (pop lst)))
(+ 0 (recursive-a (pop lst))))
0))
(recursive-a (list "a" "b" "c"))
You can run it in a web environment: https://repl.it/languages/clojure
Welcome to Stack Overflow.
By invoking recursive-a explicitly the original implementation consumes stack with each recursion. If a sufficiently large list is provided as input this function will eventually exhaust the stack and crash. There are a several ways to work around this.
One of the classic Lisp-y methods for handling situations such as this is to provide a second implementation of the function which passes the running count as an input argument to the "inner" function:
(defn recursive-a-inner [cnt lst]
(cond
(seq lst) (cond
(= (first lst) "a") (recur (inc cnt) (rest lst))
:else (recur cnt (rest lst)))
:else cnt))
(defn recursive-a [& lst]
(recursive-a-inner 0 lst))
By doing this the "inner" version allows the recursion to be pushed into tail position so that Clojure's recur keyword can be used. It's not quite as clean an implementation as the original but it has the advantage that it won't blow up the stack.
Another method for handling this is to use Clojure's loop-ing, which allows recursion within the body of a function. The result is much the same as the "inner" function above:
(defn recursive-a [& lp]
(loop [cnt 0
lst lp]
(cond
(seq lst) (cond
(= (first lst) "a") (recur (inc cnt) (rest lst))
:else (recur cnt (rest lst)))
:else cnt)))
And if we drop the requirement for explicit recursion we can make this a bit simpler:
(defn not-recursive-a [& lst]
(apply + (map #(if (= % "a") 1 0) lst)))
Best of luck.
In the spirit of learning:
You can use & or not. Both are fine. The difference is how you would then call your function, and you would have to remember to use apply when recurring.
Also, simply use first and rest. They are both safe and will work on both nil and empty lists, returning nil and empty list respectively:
(first []) ;; -> nil
(first nil) ;; -> nil
(rest []) ;; -> ()
(rest nil) ;; -> ()
So here is how I would re-work your idea:
;; With '&'
(defn count-a [& lst]
(if-let [a (first lst)]
(+ (if (= a "a") 1 0)
(apply count-a (rest lst))) ;; use 'apply' here
0))
;; call with variable args, *not* a list
(count-a "a" "b" "a" "c")
;; Without '&'
(defn count-a [lst]
(if-let [a (first lst)]
(+ (if (= a "a") 1 0)
(count-a (rest lst)))
0))
;; call with a single arg: a vector (could be a list or other )
(count-a ["a" "b" "a" "c"])
However, these are not safe, because they don't use tail-recursion, and so if your list is large, you will blow your stack!
So, we use recur. But if you don't want to define an additional "helper" function, you can instead use loop as the "recur" target:
;; With '&'
(defn count-a [& lst]
(loop [c 0 lst lst] ;; 'recur' will loop back to this point
(if-let [a (first lst)]
(recur (if (= a "a") (inc c) c) (rest lst))
c)))
(count-a "a" "b" "a" "c")
;; Without '&'
(defn count-a [lst]
(loop [c 0 lst lst]
(if-let [a (first lst)]
(recur (if (= a "a") (inc c) c) (rest lst))
c)))
(count-a ["a" "b" "a" "c"])
All that being said, this is the one I also would use:
;; With '&'
(defn count-a [& lst]
(count (filter #(= % "a") lst)))
(count-a "a" "b" "a" "c")
;; Without '&'
(defn count-a [lst]
(count (filter #(= % "a") lst)))
(count-a ["a" "b" "a" "c"])

How can I improve my solution to the Hackerrank Maximum Element challenge to avoid timeouts?

I am trying to complete the Hackerrank Maximum Element challenge found here: https://www.hackerrank.com/challenges/maximum-element/problem
My solution produces the correct output, but times out on the final test cases beginning with #17.
Initially, I used a list and loop/recur to get my answer:
(defn get-query []
(map #(Integer/parseInt %) (clojure.string/split (read-line) #" ")))
(defn stack-stepper [query stack]
(condp = (first query)
1 (conj stack (second query))
2 (rest stack)
3 (do (println (apply max stack)) stack)))
(loop [stack '()
queries-left (Integer/parseInt (read-line))]
(if (> queries-left 0)
(recur (stack-stepper (get-query) stack) (dec queries-left))))
After some research and feedback from other channels, I tried a vector instead of a list, and reduce instead of loop/recur, but the results were the same.
(defn get-query []
(map #(Integer/parseInt %) (clojure.string/split (read-line) #" ")))
(defn get-queries []
(loop [queries []
queries-left (Integer/parseInt (read-line))]
(if (= queries-left 0)
queries
(recur (conj queries (get-query)) (dec queries-left)))))
(defn stack-stepper [stack query]
(condp = (first query)
1 (conj stack (second query))
2 (pop stack)
3 (do (println (apply max stack)) stack)))
(reduce stack-stepper [] (get-queries))
I am still new to FP and Clojure and I would really like to understand what I am missing. I greatly appreciate your time and help!
HackerRank problems are often very demanding from a performance point of view.
The obvious thing to try first is using a transient vector so see if that helps. I tried this:
(let [in (clojure.string/split (slurp *in*) #"\s")
tests (first in)
input-data (map #(Integer/parseInt %) (rest in))]
(loop [v (transient [])
d input-data]
(when (seq d)
(condp = (first d)
1 (recur (conj! v (second d)) (drop 2 d))
2 (recur (pop! v) (rest d))
3 (let [pv (persistent! v)] (println (apply max pv)) (recur (transient pv) (rest d)))))))
If failed at the same point as your solution. Clearly they're looking for something cleverer than that.
The obvious bottleneck is the calculation of the max value on the current stack, which gets re-calculated each time. We can instead save the previous max value on the stack, and recover it as the current max value when we pop the stack:
(defn peek! [tvec] (get tvec (dec (count tvec))))
(let [in (clojure.string/split (slurp *in*) #"\s")
tests (first in)
input-data (map #(Integer/parseInt %) (rest in))]
(loop [v (transient [])
m 0
d input-data]
(when (seq d)
(condp = (first d)
1 (let [snd (second d)
max-now (max m snd)]
(recur (conj! v {:val snd :max-prev m}) max-now (drop 2 d)))
2 (let [popped (peek! v)
max (if popped (:max-prev popped) 0)]
(recur (pop! v) max (rest d)))
3 (do
(println m)
(recur v m (rest d)))))))
Which puts me at rank 1 on the leaderboard :)

Is there an online tool to auto-indent and format Clojure code like there are many for JSON?

There are a lot of tools online that take a JSON text and show you formatted and well indented format of the same.
Some go even further and make a nice tree-like structure: http://jsonviewer.stack.hu/
Do we have something similar for Clojure code ?
Or something that can at least auto-indent it.
If the text that I have is this :
(defn prime? [n known](loop [cnt (dec (count known)) acc []](if (< cnt 0) (not (any? acc))
(recur (dec cnt) (concat acc [(zero? (mod n (nth known cnt)))])))))
It should auto-indent to something like this:
(defn prime? [n known]
(loop [cnt (dec (count known)) acc []]
(if (< cnt 0) (not (any? acc))
(recur (dec cnt) (concat acc [(zero? (mod n (nth known cnt)))])))))
Have a look at https://github.com/xsc/rewrite-clj
It is brand new and does exactly what you are asking for.
EDIT I am still getting upvotes for this. I believe I found a better solution: You can easily do this with clojure.pprint utilizing code-dispatch without using an external library.
(clojure.pprint/write '(defn prime? [n known](loop [cnt (dec (count known)) acc []](if (< cnt 0) (not (any? acc)) (recur (dec cnt) (concat acc [(zero? (mod n (nth known cnt)))])))))
:dispatch clojure.pprint/code-dispatch)
=>
(defn prime? [n known]
(loop [cnt (dec (count known)) acc []]
(if (< cnt 0)
(not (any? acc))
(recur
(dec cnt)
(concat acc [(zero? (mod n (nth known cnt)))])))))
I'm not aware of any online services which do this, but there are Clojure libraries which serve this purpose. clojure.pprint comes with Clojure (the key function is clojure.pprint/pprint); Brandon Bloom's fipp is a significantly faster alternative.
Note that neither of these is particularly likely to format code as a programmer armed with Emacs would; they're close enough to be useful, however, and for literal data (not intended to be interpreted as code) may well match human standards.
Following up on this - there is now http://pretty-print.net which will serve this very purpose for EDN and Clojure Code.
There is now https://github.com/weavejester/cljfmt for that purpose
Instructions
Add it in your Leiningen plugins:
:plugins [[lein-cljfmt "0.6.1"]]
Then, to autoformat all code in your project:
lein cljfmt fix
Sample
Your sample code will become:
(defn prime? [n known] (loop [cnt (dec (count known)) acc []] (if (< cnt 0) (not (any? acc))
(recur (dec cnt) (concat acc [(zero? (mod n (nth known cnt)))])))))
After adding some linebreaks and reformatting again:
(defn prime? [n known]
(loop [cnt (dec (count known)) acc []]
(if (< cnt 0) (not (any? acc))
(recur (dec cnt) (concat acc [(zero? (mod n (nth known cnt)))])))))

Binary search in clojure (implementation / performance)

I wrote a binary search function as part of a larger program, but it seems to be slower than it should be and profiling shows a lot of calls to methods in clojure.lang.Numbers.
My understanding is that Clojure can use primitives when it can determine that it can do so. The calls to the methods in clojure.lang.Numbers seems to indicate that it's not using primitives here.
If I coerce the loop variables to ints, it properly complains that the recur arguments are not primitive. If i coerce those too, the code works again but again it's slow. My only guess is that (quot (+ low-idx high-idx) 2) is not producing a primitive but I'm not sure where to go from here.
This is my first program in Clojure so feel free to let me know if there are more cleaner/functional/Clojure ways to do something.
(defn binary-search
[coll coll-size target]
(let [cnt (dec coll-size)]
(loop [low-idx 0 high-idx cnt]
(if (> low-idx high-idx)
nil
(let [mid-idx (quot (+ low-idx high-idx) 2) mid-val (coll mid-idx)]
(cond
(= mid-val target) mid-idx
(< mid-val target) (recur (inc mid-idx) high-idx)
(> mid-val target) (recur low-idx (dec mid-idx))
))))))
(defn binary-search-perf-test
[test-size]
(do
(let [test-set (vec (range 1 (inc test-size))) test-set-size (count test-set)]
(time (count (map #(binary-search2 test-set test-set-size %) test-set)))
)))
First of all, you can use the binary search implementation provided by java.util.Collections:
(java.util.Collections/binarySearch [0 1 2 3] 2 compare)
; => 2
If you skip the compare, the search will be faster still, unless the collection includes bigints, in which case it'll break.
As for your pure Clojure implementation, you can hint coll-size with ^long in the parameter vector -- or maybe just ask for the vector's size at the beginning of the function's body (that's a very fast, constant time operation), replace the (quot ... 2) call with (bit-shift-right ... 1) and use unchecked math for the index calculations. With some additional tweaks a binary search could be written as follows:
(defn binary-search
"Finds earliest occurrence of x in xs (a vector) using binary search."
([xs x]
(loop [l 0 h (unchecked-dec (count xs))]
(if (<= h (inc l))
(cond
(== x (xs l)) l
(== x (xs h)) h
:else nil)
(let [m (unchecked-add l (bit-shift-right (unchecked-subtract h l) 1))]
(if (< (xs m) x)
(recur (unchecked-inc m) h)
(recur l m)))))))
This is still noticeably slower than the Java variant:
(defn java-binsearch [xs x]
(java.util.Collections/binarySearch xs x compare))
binary-search as defined above seems to take about 25% more time than this java-binsearch.
in Clojure 1.2.x you can only coerce local variables and they can't cross functions calls.
starting in Clojure 1.3.0 Clojure can use primative numbers across function calls but not through Higher Order Functions such as map.
if you are using clojure 1.3.0+ then you should be able to accomplish this using type hints
as with any clojure optimization problem the first step is to turn on (set! *warn-on-reflection* true) then add type hints until it no longer complains.
user=> (set! *warn-on-reflection* true)
true
user=> (defn binary-search
[coll coll-size target]
(let [cnt (dec coll-size)]
(loop [low-idx 0 high-idx cnt]
(if (> low-idx high-idx)
nil
(let [mid-idx (quot (+ low-idx high-idx) 2) mid-val (coll mid-idx)]
(cond
(= mid-val target) mid-idx
(< mid-val target) (recur (inc mid-idx) high-idx)
(> mid-val target) (recur low-idx (dec mid-idx))
))))))
NO_SOURCE_FILE:23 recur arg for primitive local: low_idx is not matching primitive,
had: Object, needed: long
Auto-boxing loop arg: low-idx
#'user/binary-search
user=>
to remove this you can type hint the coll-size argument
(defn binary-search
[coll ^long coll-size target]
(let [cnt (dec coll-size)]
(loop [low-idx 0 high-idx cnt]
(if (> low-idx high-idx)
nil
(let [mid-idx (quot (+ low-idx high-idx) 2) mid-val (coll mid-idx)]
(cond
(= mid-val target) mid-idx
(< mid-val target) (recur (inc mid-idx) high-idx)
(> mid-val target) (recur low-idx (dec mid-idx))
))))))
it is understandably difficult to connect the auto-boxing on line 10 to the coll-size parameter because it goes through cnt then high-idx then mid-ixd and so on, so I generally approach these problems by type-hinting everything until I find the one that makes the warnings go away, then remove hints so long as they stay gone