Please comment how to restructure the following function more readable and less parentheses.
(defn forwardDifference2nd [fn x h]
(->
(/ (+ (-
(fn (+ (+ x h) h))
(* (fn (+ x h)) 2.0))
(fn x))
(Math/pow h 2))))
Source Code
(def x 1.0)
(def h 0.1)
(defn forwardDifference2nd [fn x h]
(->
(/ (+ (-
(fn (+ (+ x h) h))
(* (fn (+ x h)) 2.0))
(fn x))
(Math/pow h 2))))
(defn myPolynomial [x]
(->
(+ (* 2
(Math/pow x 3))
(* 4
(Math/pow x 2)))
(- (* 5 x))))
(forwardDifference2nd myPolynomial x h)
Here is one example:
(defn forwardDifference2nd [f x h]
(let [fh #(f (+ x (* h %)))]
(/ (+ (fh 2) (* -2 (fh 1)) (f x))
h h)))
Simplifications:
Remove (-> ...)
Factor out similar looking expressions into local function
Flatten nested sums and differences
Replace (/ ... (Math/pow h 2)) by (/ ... h h)
Update:
Your computation could more generally be expressed as
(defn difference-at-depth [f x h depth]
(if (zero? depth)
(f x)
(let [depth (dec depth)]
(/ (- (difference-at-depth f (+ x h) h depth)
(difference-at-depth f x h depth))
h))))
(defn forwardDifference2nd [f x h]
(difference-at-depth f x h 2))
but this code is obviously longer. On the other hand, it better shows what is going on mathematically and is in that sense arguably more readable.
Locally naming with let and then using named parts for calculation not only enhances readability of formulas but also is computationally more efficient.
For re-occuring patterns like a polynom in polynomial, define a function with a name.
(defn forward-difference-2nd [f x h]
(let [f_xhh (f (+ x h h))
f_xh (f (+ x h))
f_x (f x)
h**2 (* h h)]
(/ (- f_xhh f_xh f_xh f_x) h**2)))
(defn polynom [coeff x power] (* coeff (Math/pow x power)))
(defn my-polynomial [x]
(+ (polynom 2 x 4) (polynom 4 x 2) (polynom -5 x 1)))
(def x 1.0)
(def h 0.1)
(forward-difference-2nd my-polynomial x h)
Related
One of my favorite ways to test the power of a language I'm learning is to try and implement various fixed-point combinators. Since I'm learning Clojure (though I'm not new to lisps), I did the same for it.
First, a little "testable" code, factorial:
(def !'
"un-fixed factorial function"
(fn [f]
(fn [n]
(if (zero? n)
1
(* n (f (dec n)))))))
(defn !
"factorial"
[n]
(if (zero? n)
1
(apply * (map inc (range n)))))
For any combinator c I implement, I want to verify that ((c !') n) is equal to (! n).
We start with the traditional Y:
(defn Y
"pure lazy Y combinator => stack overflow"
[f]
(let [A (fn [x] (f (x x)))]
(A A)))
But of course Clojure is not nearly so lazy as that, so we pivot to Z:
(defn Z
"strict fixed-point combinator"
[f]
(let [A (fn [x] (f (fn [v] ((x x) v))))]
(A A)))
And indeed, it holds that (= ((Z !') n) (! n)).
Now comes my issue: I cannot get either of U or the Turing combinator (theta-v) to work correctly. I suspect with U it's a language limit, while with theta-v I'm more inclined to believe it's a misread of Wikipedia's notation:
(defn U
"the U combinator => broken???"
[f]
(f f))
(defn theta-v
"Turing fixed-point combinator by-value"
[f]
(let [A (fn [x] (fn [y] (y (fn [z] ((x x) y) z))))]
(A A)))
A sample REPL experience:
((U !') 5)
;=> Execution error (ClassCastException) at fix/!'$fn (fix.clj:55).
;=> fix$_BANG__SINGLEQUOTE_$fn__180 cannot be cast to java.lang.Number
((theta-v !') 5)
;=> Execution error (ClassCastException) at fix/theta-v$A$fn (fix.clj:36).
;=> java.lang.Long cannot be cast to clojure.lang.IFn
Can anyone explain
Why these implementations of U and theta-v are not working; and
How to fix them?
Your definition of theta-v is wrong for two reasons. The first is pretty obvious: you accept f as a parameter and then ignore it. A more faithful translation would be to use def style, as you have for your other functions:
(def theta-v
"Turing fixed-point combinator by-value"
(let [A (fn [x] (fn [y] (y (fn [z] ((x x) y) z))))]
(A A)))
The second reason is a bit sneakier: you translated λz.xxyz to (fn [z] ((x x) y) z), remembering that lisps need more parentheses to denote function calls that are implicit in lambda-calculus notation. However, you missed one set: just as x x y z would have meant "evaluate x twice, then y once, then finally return z", what you wrote means "evaluate ((x x) y), then throw away that result and return z". Adding the extra set of parentheses yields a working theta-v:
(def theta-v
"Turing fixed-point combinator by-value"
(let [A (fn [x] (fn [y] (y (fn [z] (((x x) y) z)))))]
(A A)))
and we can demonstrate that it works by calculating some factorials:
user> (map (theta-v !') (range 10))
(1 1 2 6 24 120 720 5040 40320 362880)
As for U: to use the U combinator, functions being combined must change how they self-call, meaning you would need to rewrite !' as well:
(def U [f] (f f))
(def ! (U (fn [f]
(fn [n]
(if (zero? n)
1
(* n ((f f) (dec n))))))))
Note that I have changed (f (dec n)) to ((f f) (dec n)).
I wanted to learn Clojure and started with a Mandelbrot generator using quil, I got it to work - however it takes some time to generate images and is a massive resource hog. Any advice for how to make it faster or if you spot any un-clojure-esque parts of my code.
Core.clj
(ns frac.core
(:require [quil.core :as q])
(:require [frac.complex :refer :all]))
(def scale (atom 0.01))
(def xoff (atom -200))
(def yoff (atom -200))
(def its 50)
(defn mandelbrot [r i]
(count (take its (take-while #(<= (modu %) 2) (iterate #( add (mul % %) [r i]) [r i])))))
(defn gen []
(let [p (q/pixels)
w (q/width)
h (q/height)]
(doseq [x (range w) y (range h)]
(let [m (mandelbrot (* #scale (+ x #xoff)) (* #scale (+ y #yoff)))
c (if (= m its) 0 m)]
(aset p (+ x (* y w)) (q/color (* 1.5 c) (* 4 c) (* 5.2 c))))))
(q/update-pixels))
(defn setup []
(gen))
(defn draw [])
(defn click []
(swap! xoff #(+ (q/mouse-x) (- (/ (q/width) 2)) %))
(swap! yoff #(+ (q/mouse-y) (- (/ (q/height) 2)) %))
(gen))
(defn wheel [z]
(swap! scale #(if (pos? z) (* 1.1 %) (* 0.9 %)))
(prn #scale)
(gen))
(q/defsketch example
:title "Mandel"
:setup setup
:draw draw
:size [400 400]
:mouse-clicked click
:mouse-wheel wheel)
(defn -main [& args])
Complex.clj
(ns frac.complex)
(defn mul [z1 z2]
(let [r1 (first z1)
i1 (second z1)
r2 (first z2)
i2 (second z2)]
[(- (* r1 r2) (* i1 i2)) (+ (* r1 i2) (* r2 i1))]))
(defn add [z1 z2]
(let [r1 (first z1)
i1 (second z1)
r2 (first z2)
i2 (second z2)]
[(+ r1 r2) (+ i1 i2)]))
(defn modu [z]
(let [r (first z)
i (second z)]
(Math/sqrt (+ (* r r) (* i i)))))
Try set this:
(set! *unchecked-math* :warn-on-boxed)
and remove all warnings. Use type hints as needed.
So currently, I wrote a Clojure code to do Trapezoidal integration of a polynomial function in HackerRank.com:
https://www.hackerrank.com/challenges/area-under-curves-and-volume-of-revolving-a-curv
(defn abs[x]
(max x (- 0 x))
)
(defn exp[x n]
(if (> n 0)
(* x (exp x (- n 1)))
1
)
)
(defn fact[x]
(if (> x 0)
(* x (fact (- x 1)))
1)
)
(defn func[x lst1 lst2]
((fn step [sum lst1 lst2]
(if (> (.size lst1) 0)
(step (+ sum (* (last lst1) (exp x (last lst2)))) (drop-last lst1) (drop-last lst2))
sum
)
)
0 lst1 lst2
)
)
(defn integrate[f a b]
(def h 0.001)
(def n (/ (abs (- b a)) h))
((fn step[i sum]
(if (< i n)
(step (+ i 1) (+ sum (f (+ (* i h) a))))
(* h (+ (/(+ (f a) (f b)) 2) sum))
)
) 0 0)
)
(defn volumeIntegral[f a b]
(defn area[r]
(* 3.14159265359 (* r r)))
(def h 0.001)
(def n (/ (abs (- b a)) h))
((fn step[i sum]
(if (< i n)
(step (+ i 1) (+ sum (area (f (+ (* i h) a)))))
(* h (+ (/ (+ (f a) (f b)) 2) sum))
)
) 0 0)
)
(defn lineToVec[line_str] (clojure.string/split line_str #"\s+"))
(defn strToDouble [x] (Double/parseDouble (apply str (filter #(Character/isDigit %) x))))
(defn readline[vec]
((fn step[list vec]
(if (> (.size vec) 0)
(step (conj list (last vec)) (drop-last vec))
list
)
) '() vec)
)
(integrate (fn [x] (func x '(1 2 3 4 5 6 7 8) '(-1 -2 -3 -4 1 2 3 4))) 1 2)
(volumeIntegral (fn [x] (func x '(1 2 3 4 5 6 7 8) '(-1 -2 -3 -4 1 2 3 4))) 1 2)
However, the output I have is:
107.38602491666647
45611.95754801859
While is supposed to be around:
101.4
41193.0
My code passed the first two test cases, but didn't manage to pass the rest. I assume is because of the issue accuracy. I looked through my code several times but couldn't seem to make it better. What am I doing wrong here ? Thank you.
Your exp function isn't quite right -- it doesn't handle negative exponents correctly. Probably best just to use Math/pow.
The other thing you could do is adjust your h value in volumeIntegral but to avoid stack issues, use recur (which gives you tail recursion), e.g. here's a slightly modified version:
(defn volume-integral [f a b]
(defn area[r]
(* Math/PI (* r r)))
(def h 0.000001)
(def n (/ (abs (- b a)) h))
((fn [i sum]
(if (not (< i n))
(* h (+ (/ (+ (f a) (f b)) 2) sum))
(recur (+ i 1) (+ sum (area (f (+ (* i h) a)))))))
0 0))
(I did the something similar with integral.) All in all, I wasn't able to quite hit the second figure, but this should get you on the right track:
101.33517384995224
41119.11576557253
I'm new to Clojure and am trying to write a Newton's method function using the built in iterate. I have tried several things that resulted in the following code. Any ideas as to why this is only returning empty parens? I'm open to new ideas as well.
(defn within-tol?
"returns true if the guess is within the given tolerance"
[guess x tolerance]
(< (abs (- (square guess) x)) tolerance))
(defn next-guess
[guess x]
(average guess (/ x guess)))
(defn average
[x y]
(float (/ (+ x y) 2)))
(defn abs
[x]
(cond
(< x 0) (- x)
:else x))
(defn square
[x]
(* x x))
(defn sqrt-iter
[guess x tolerance]
(if (within-tol? guess x tolerance) guess
(sqrt-iter (next-guess guess x) x tolerance)))
(defn sqrt
[guess x tolerance]
(take-while #(within-tol? % x tolerance) (iterate #((sqrt % x tolerance)) guess)))
Seems your sqrt is wrong as it does not use next-guess
Try that
(defn sqrt
[guess x tolerance]
(first (drop-while #(not (within-tol? % x tolerance))
(iterate #(next-guess % x) guess))))
Example:
(sqrt 1 169 0.01) => 13.0
(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}