I have been stuck on this one for a while and cant figure it out. Why is the function not evaluating for values greater or equal than 2? It works fine for values under it but anything above and it just prints the output seen in the pic
((fn fib
([x] (cond
(zero? x) []
(= x 1) [1]
(>= x 2) fib (- x 2) [1 1]))
([x seq] (if (zero? x)
seq
(recur (dec x) (conj seq (+ (last seq) (nth seq (- (count seq) 2)))))))) 3)
enter image description here
You forgot one parenthesis on this line, before fib:
(>= x 2) fib (- x 2) [1 1]))
After you will add it, this code will work. Just note that your variables shouldn't have the same name as already existing functions- you were shadowing core function seq.
((fn fib
([x] (cond
(zero? x) []
(= x 1) [1]
(>= x 2) (fib (- x 2) [1 1])))
([x values]
(if (zero? x)
values
(recur (dec x)
(conj values (+ (last values)
(nth values (- (count values) 2)))))))) 3)
Related
In the following code, I need to compute the maximum of the sum of one element from keyboards and one from drives, subject that the sum should be less or equal to s.
(def s 10)
(def keyboards '(3 1))
(def drives '(5 2 8))
(let [k (sort (fn [x y] (> x y)) keyboards) ; sort into decreasing
d (sort (fn [x y] (> x y)) drives) ; sort into decreasing
]
(loop [k1 (first k) ks (rest k) d1 (first d) ds (rest d)]
(cond
(or (nil? k1) (nil? d1)) -1 ; when one of the list is empty
(< (+ k1 d1) s) (+ k1 d1) ; whether (+ k1 d1) can be saved to compute once?
(and (empty? ks) (empty? ds)) -1
(empty? ks) (if (< (+ k1 (first ds)) s) (+ k1 (first ds)) -1) ; whether (+ k1 (first ds)) can be saved once?
(empty? ds) (if (< (+ d1 (first ks)) s) (+ d1 (first ks)) -1) ; whether (+ d1 (first ks)) can be saved once?
:else (let [bs (take-while #(< % s) [ (+ k1 (first ds)) (+ (first ks) d1) ])]
(if (empty? bs) (recur (first ks) (rest ks) (first ds) (rest ds))
(apply max bs))))))
As indicated in the comments, I wonder if there is any way to further optimize the repeated add operation in the conditional expressions.
It may not be optimal to use let bindings to compute them all before the condition checkings, as only one of the condition would be true, thus the computations for the other conditions would be wasted.
I wonder if Clojure compiler would be smart enough to optimize the repeated computation for me, or there is a clever expression to make the operation to be performed only once in both the checking and return value?
Any suggestion to make the code more idiomatic would be appreciated.
This sounds kind of like the knapsack problem. There are more computationally efficient ways to compute it, but if you are dealing with two or three small lists which are less than a few hundred, and if it is not a critical piece of code that is running in a hot loop, consider the much simpler:
(let [upper-limit 10
keyboards [3 1]
drives [5 2 8]]
(apply max
(for [k keyboards
d drives
:let [sum (+ k d)]
:when (<= sum upper-limit)]
sum)))
You perform your (potentially expensive) computation only once (in the :let binding), which is what you really were asking for. This is O(n^2), but if it meets the criteria above, it is a solution which can be understood easily to the reader; thus, it is maintainable. If it's critical that it be as efficient as possible, consider more algorithmically efficient solutions.
Edited by Yu Shen:
There is a slight problem when there no eligible sum. It may be improved as follows:
(let [upper-limit 10
keyboards [3 1]
drives [5 2 8]
eligbles (for [k keyboards
d drives
:let [sum (+ k d)]
:when (<= sum upper-limit)]
sum)]
(if (empty? eligbles)
nil
(apply max eligbles)))
If you want to keep the structure of your current code, you can use Mark Engelberg's better-cond library:
(require '[better-cond.core :as b])
(def s 10)
(def keyboards '(3 1))
(def drives '(5 2 8))
(let [k (sort (fn [x y] (> x y)) keyboards) ; sort into decreasing
d (sort (fn [x y] (> x y)) drives)] ; sort into decreasing
(loop [k1 (first k) ks (rest k) d1 (first d) ds (rest d)]
(b/cond
(or (nil? k1) (nil? d1)) -1 ; when one of the list is empty
:let [x (+ k1 d1)]
(< x s) x
(and (empty? ks) (empty? ds)) -1
:let [y (+ k1 (first ds))]
(empty? ks) (if (< y s) (dec y))
:let [z (+ d1 (first ks))]
(empty? ds) (if (< z s) (dec z))
:else (let [bs (take-while #(< % s) [(+ k1 (first ds)) (+ (first ks) d1)])]
(if (empty? bs) (recur (first ks) (rest ks) (first ds) (rest ds))
(apply max bs))))))
I'm new to clojure, attempting to write a function (all-bit-seqs n) that generates all bit strings of length n as a list. So if I were to call (all-bit-seqs 2), it would output ((0 0) (0 1) (1 0) (1 1)) in any order. However, I am getting a NullPointerException when I call the helper function rest-bit-seqs, and I can't figure out why. My code is as follows, any help would be appreciated.
(defn not-bit [x]
(* -1 (- x 1))
)
(defn inc-bit-seq [x]
(cond
(= 0 (not-bit (first x))) (cons 0 (inc-bit-seq (rest x)))
:else (cons 1 (rest x))
)
)
(defn pow [x, y]
(cond
(not= y 0) (* x (pow x (- y 1)))
:else 1
)
)
(defn rest-bit-seqs [n, x, lst]
(cond
(not= x (pow 2 n)) (cons lst (rest-bit-seqs n (+ 1 x) (inc-bit-seq lst)))
:else '()
)
)
(defn zero-seq [n]
(cond
(= n 0) '()
:else (cons 0 (zero-seq (- n 1)))
)
)
(defn all-bit-seqs [n]
(rest-bit-seqs n 0 (zero-seq n))
)
that is because you don't handle the case of an empty sequence here:
(defn inc-bit-seq [x]
(cond
(= 0 (not-bit (first x))) (cons 0 (inc-bit-seq (rest x)))
:else (cons 1 (rest x))
)
)
so at one point you pass (first x) (which is nil for an empty seq) to not-bit.
the following fix solves this:
(defn inc-bit-seq [x]
(when (seq x)
(cond
(= 0 (not-bit (first x))) (cons 0 (inc-bit-seq (rest x)))
:else (cons 1 (rest x))
))
)
in repl:
user> (all-bit-seqs 2)
((0 0) (1 0) (0 1) (1 1))
the other things that are totally weird here, is your choice of cond instead of simple if, and uncommon formatting. I would consider rewriting the code this way:
(defn not-bit [x]
(* -1 (- x 1)))
(defn inc-bit-seq [x]
(when (seq x)
(if (zero? (not-bit (first x)))
(cons 0 (inc-bit-seq (rest x)))
(cons 1 (rest x)))))
(defn pow [x, y]
(if-not (zero? y)
(* x (pow x (- y 1)))
1))
(defn rest-bit-seqs [n, x, lst]
(when-not (== x (pow 2 n))
(cons lst (rest-bit-seqs n (+ 1 x) (inc-bit-seq lst)))))
(defn zero-seq [n]
(when-not (zero? n)
(cons 0 (zero-seq (- n 1)))))
(defn all-bit-seqs [n]
(rest-bit-seqs n 0 (zero-seq n)))
(it's about style, haven't looked at overall code correctness)
Your error is here:
(= 0 (not-bit (first x)))
If x is empty, (first x) will return nil, so this will happen:
(= 0 (not-bit nil))
(= 0 (* -1 (- nil 1))
When you try to evaluate (- nil 1), you'll get a NullPointerException.
The quick-and-dirty way to fix the problem is to get rid of not-bit and replace that condition with
(= 1 (first x))
However, there are much shorter/simpler ways to solve this problem. Here's one way:
(defn inc-bit-seq [[head & tail]]
(if (zero? head)
(cons 1 tail)
(cons 0 (inc-bit-seq tail))))
(defn all-bit-seqs [n]
(take (bit-shift-left 1 n)
(iterate inc-bit-seq (repeat n 0))))
Another way would be to use strings:
(defn pad-first [n x xs]
(concat (repeat (- n (count xs)) x) xs))
(defn all-bit-seqs [n]
(map (comp (partial pad-first n 0)
(partial map #(Character/getNumericValue %))
#(Long/toBinaryString %))
(range (bit-shift-left 1 n))))
Is there anyway i can return a value from a loop since the recursion has to be at the tail
(ns for)
(defn abc [y]
(loop [x 10]
(when (> x 2)
(if (= 2 3) (do (println "test") (recur (- x 2)))
(do (let [x (+ 1 x)
y 2] (println y) (recur (- x 2))))))))
(abc 1)
is there anyway i can return a value for the function by taking y as a parameter and updating a new value of y. However, the recur part has to be at the last line of the code hence i am unable to put y as the last line of the code.
Example
(ns for)
(defn abc [y]
(loop [x 10]
(when (> x 2)
(if (= 2 3) (do (println "test") (recur (- x 2)))
(do (let [x (+ 1 x)
y 2] (println y) (recur (- x 2)))))))
y)
(abc 1)
This would give me an error since recur has to be the last line of code. I have looked at similar questions and it says to put the return value at the end of the if loop which i tried but failed which gives me an exception thatthe recursion can only happen at the tail
I guess you meant this:
(defn abc [y]
(loop [x 10
y nil]
(if (> x 2)
(if (= 2 3)
(do (println "test")
(recur (- x 2) nil))
(do (let [x (+ 1 x)
y 2]
(println y)
(recur (- x 2) y))))
y)))
Update. Without unnecessary parts it would be
(defn abc [y]
(loop [x 10]
(if (> x 2)
(do (println 2)
(recur (- x 1)))
2)))
which is the same as
(defn abc [_]
(dotimes [_ 8] (println 2))
2)
I am trying to make this sample program work
(defn foo
([x] (foo x []))
([x current]
(when (> x 0)
(recur (dec x) (conj current x)))))
When I call this function (foo 5), I should get [1 2 3 4 5], however it only returns nil. What am I doing wrong?
Thanks,
Murtaza
Your recursion doesn't have a return expression i.e when then when is false the recursion terminates and it returns nil. You can fix this using if as:
(defn foo
([x] (foo x []))
([x current]
(if (> x 0)
(recur (dec x) (conj current x))
current)))
This will return [5 4 3 2 1] for (foo 5) as you are using vector as return value and conj on vector appends the item at the end of the vector. You can either reverse the vector or use list i.e in place of (foo x []) use (foo x '())
The code below works. I was not returning the final value.
(defn foo
([x] (foo x []))
([x current]
(if (> x 0)
(recur (dec x) (conj current x))
current)))
I have corrected your original program to use (if (= x 0) instead of (when (> x 0), and this returns [1 2 3 4 5].
(defn foo
([x] (foo x []))
([x current]
(if (= x 0)
(apply vector (sort < current))
(recur (dec x) (conj current x)))))
(def throws 10)
(defn r-squared [x y]
(+ (* (- 0.5 x) (- 0.5 x))
(* (- 0.5 y) (- 0.5 y))))
(loop [hits 0]
(let [x (rand)
y (rand)]
; still inside the let
(if (< (r-squared x y) 0.25) ;is it a hit or not? if not, try again
(recur (inc hits))
(* 4 (/ hits throws)))))
I got that code working and running until the if condition is true. How can I rewrite it so it takes X as parameter and runs X times?
I basically want to call (r-squared 100) and get how many hits I got as return value.
I think this is what you want, if understend question correctly.
(defn test [n]
(loop [hits 0 n n]
(let [x (rand)
y (rand)]
(if (< n 0)
hits ;// you can put (* 4 (/ hits throws)) here
(if (< (r-squared x y) 0.25)
(recur (inc hits) (dec n))
(recur hits (dec n)))))))
Didn't eval it, so parn might be slightly wrong.
(def throws 10)
(defn r-squared [x y]
(+ (* (- 0.5 x) (- 0.5 x))
(* (- 0.5 y) (- 0.5 y))))
(defn test-r-squared [n]
(loop [hits (int 0) n (int n)]
(let [x (rand)
y (rand)]
; still inside the let
(if (< n 0)
(* 4 (/ hits throws))
(if (< (r-squared x y) 0.25) ;is it a hit or not? if not, try again
(recur (inc hits) (dec n))
(recur hits (dec n)))))))
(defn r-squared [x y]
(+ (* (- 0.5 x) (- 0.5 x))
(* (- 0.5 y) (- 0.5 y))))
(defn hit[]
(let [x (rand) y (rand)]
(< (r-squared x y) 0.25)))
(frequencies (for [i (range 1000)] (hit))) ; {true 787, false 213}