I want to perform the following nested operations until the experession is satisfied..
Is there a :until keyword which stops doing further operations when the condition matches.?
This command generates the Pythagoran Triplet 3 4 5. I dont want it to do anything else once it gets to that sequence of numbers.
(for [a (range 1 100)
b (range 1 100)
c (list (Math/sqrt (+ (Math/pow (int a) 2) (Math/pow (int b) 2))))
:when (= 12 (+ a b c))]
(list a b c))
:while is a short-circuiting test in for expressions. List elements will be generated until the first time it encounters a failing test.
In your case
(for [<code omitted> :while (not (= 12 (+ a b c)))] (list a b c))
would stop generating elements as soon as it found the triplet summing to 12.
One problem though, it doesn't do what you're expecting. The triplet itself would not be part of the result since it failed the test.
A list comprehension may not be the best solution if you are only looking for a single matching result. Why not just use a loop?
(loop [xs (for [a (range 1 100)
b (range 1 100)] [a, b])]
(when (seq xs)
(let [[a, b] (first xs)
c (Math/sqrt (+ (Math/pow (int a) 2)
(Math/pow (int b) 2)))]
(if (not (= 12 (+ a b c)))
(recur (next xs))
(list a b c)))))
Since for yields a lazy sequence you will get the desired result by picking the first element:
(first (for [a (range 1 100)
b (range 1 100)
c (list (Math/sqrt (+ (Math/pow (int a) 2)
(Math/pow (int b) 2))))
:when (= 12 (+ a b c))]
(list a b c))
Only the first element of the generated list is computed due to laziness, which can be demonstrated with a side effect:
user=> (first
(for [a (range 1 100)
b (range 1 100)
c (list (Math/sqrt (+ (Math/pow (int a) 2)
(Math/pow (int b) 2))))
:when (= 12 (+ a b c))]
(do (println "working...")
(list a b c))))
working...
(3 4 5.0)
(for ...) comes with a :let modifier so there is no need to wrap c in a list:
(for [a (range 1 100)
b (range 1 100)
:let [c (Math/sqrt (+ (Math/pow (int a) 2)
(Math/pow (int b) 2)))]
:when (= 12 (+ a b c))]
(list a b c))
Related
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 tried to print a number to the console: The mathfunction should return
the sum of the squares of the two larger numbers
(ns myapp.core)
(defn mathfunction [a, b, c]
(let [x (max a b c)
lst (remove #{x} '(a b c))
y (max((first lst) (first (rest lst))))]
(+ (Math/sqrt x) (Math/sqrt y))))
(defn -main [& args]
(println (mathfunction(1 5 3))))
And just to make sure that not my mathfunction is the problem:
(defn -main [& args]
(println 5.4))
java.lang.ClassCastException: java.lang.Long cannot be cast to
clojure.lang.IFn
So what did i do wrong?
You have a problem in :
(mathfunction(1, 5, 3))
What you need is:
(mathfunction '(1, 5, 3))
Or:
(mathfunction (list 1 2 3))
Because in (mathfunction (1, 5, 3)) , 1 is a number not a function and that is why you are getting:
java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn
Also, this is wrong for the same reason above:
(max ((first lst) (first (rest lst))))
And what you need is:
(max (first lst) (first (rest lst)))
Remember that in Lisp, the first element in list is a special thing. It is called: Function Position.
For that what you want to do, that way may be more idiomatic for clojure:
(defn mathfunction [& args]
(let [a (apply max args)
rem (remove #(= % a) args)
b (apply max rem)]
(+ (Math/sqrt a) (Math/sqrt b))))
Also you need to call it like (mathfunction 1 2 3) and not like (mathfunction (1 2 3)).
The latte ris interpreted as a funciton call with 1 as the function and 2,3 as the parameters.
I'm trying to implement a method that will take a list of lists and return a the cartesian product of these lists.
Here's what I have so far:
(defn cart
([] '())
([l1] (map list l1))
([l1 l2]
(map
(fn f[x] (map
(fn g [y] (list x y))
l2))
l1)
)
)
(defn cartesian-product [& lists]
(reduce cart lists)
)
;test cases
(println (cartesian-product '(a b) '(c d))) ; ((a c) (a d) (b c) (b d))
(println (cartesian-product ())) ;()
(println (cartesian-product '(0 1))) ; ((0) (1))
(println (cartesian-product '(0 1) '(0 1))) ; ((0 0) (0 1) (1 0) (1 1))
(println (apply cartesian-product (take 4 (repeat (range 2))))) ;((0 0 0 0) (0 0 0 1) (0 0 1 0) (0 0 1 1) (0 1 0 0) (0 1 0 1) (0 1 1 0) (0 1 1 1) (1 0 0 0) (1 0 0 1) (1 0 1 0) (1 0 1 1) (1 1 0 0) (1 1 0 1) (1 1 1 0) (1 1 1 1))
The problem is my solution is really 'brackety'.
(((a c) (a d)) ((b c) (b d)))
()
(0 1)
(((0 0) (0 1)) ((1 0) (1 1)))
(((((((0 0) (0 1)) 0) (((0 0) (0 1)) 1)) 0) (((((0 0) (0 1)) 0) (((0 0) (0 1)) 1)) 1)) ((((((1 0) (1 1)) 0) (((1 0) (1 1)) 1)) 0) (((((1 0) (1 1)) 0) (((1 0) (1 1)) 1)) 1)))
I tried adding
(apply concat(reduce cart lists))
but then I get a crash like so:
((a c) (a d) (b c) (b d))
()
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:494)
So, I think I'm close but missing something. However since I'm so new to clojure and functional programming I could be on the completely wrong track. Please help! :)
This is a lot easier to do as a for-comprehension than by trying to work out the recursion manually:
(defn cart [colls]
(if (empty? colls)
'(())
(for [more (cart (rest colls))
x (first colls)]
(cons x more))))
user> (cart '((a b c) (1 2 3) (black white)))
((a 1 black) (a 1 white) (a 2 black) (a 2 white) (a 3 black) (a 3 white)
(b 1 black) (b 1 white) (b 2 black) (b 2 white) (b 3 black) (b 3 white)
(c 1 black) (c 1 white) (c 2 black) (c 2 white) (c 3 black) (c 3 white))
The base case is obvious (it needs to be a list containing the empty list, not the empty list itself, since there is one way to take a cartesian product of no lists). In the recursive case, you just iterate over each element x of the first collection, and then over each cartesian product of the rest of the lists, prepending the x you've chosen.
Note that it's important to write the two clauses of the for comprehension in this slightly unnatural order: swapping them results in a substantial slowdown. The reason for this is to avoid duplicating work. The body of the second binding will be evaluated once for each item in the first binding, which (if you wrote the clauses in the wrong order) would mean many wasted copies of the expensive recursive clause. If you wish to be extra careful, you can make it clear that the two clauses are independent, by instead writing:
(let [c1 (first colls)]
(for [more (cart (rest colls))
x c1]
(cons x more)))
I would check https://github.com/clojure/math.combinatorics it has
(combo/cartesian-product [1 2] [3 4])
;;=> ((1 3) (1 4) (2 3) (2 4))
For the sake of comparison, in the spirit of the original
(defn cart
([xs]
xs)
([xs ys]
(mapcat (fn [x] (map (fn [y] (list x y)) ys)) xs))
([xs ys & more]
(mapcat (fn [x] (map (fn [z] (cons x z)) (apply cart (cons ys more)))) xs)))
(cart '(a b c) '(d e f) '(g h i))
;=> ((a d g) (a d h) (a d i) (a e g) (a e h) (a e i) (a f g) (a f h) (a f i)
; (b d g) (b d h) (b d i) (b e g) (b e h) (b e i) (b f g) (b f h) (b f i)
; (c d g) (c d h) (c d i) (c e g) (c e h) (c e i) (c f g) (c f h) (c f i))
I know I'm late to the party -- I just wanted to add a different approach, for the sake of completeness.
Compared to amalloy's approach, it is lazy too (the parameter lists are eagerly evaluated, though) and slightly faster when all results are required (I tested them both with the demo code below), however it is prone to stack overflow (much like the underlying for comprehension it generates and evaluates) as the number of lists increases. Also, keep in mind that eval has a limit to the size of the code it can be passed to.
Consider first a single instance of the problem: You want to find the cartesian product of [:a :b :c] and '(1 2 3). The obvious solution is to use a for comprehension, like this:
(for [e1 [:a :b :c]
e2 '(1 2 3)]
(list e1 e2))
; ((:a 1) (:a 2) (:a 3) (:b 1) (:b 2) (:b 3) (:c 1) (:c 2) (:c 3))
Now, the question is: Is it possible to generalize this in a way that works with an arbitrary number of lists? The answer here is affirmative. This is what the following macro does:
(defmacro cart [& lists]
(let [syms (for [_ lists] (gensym))]
`(for [~#(mapcat list syms lists)]
(list ~#syms))))
(macroexpand-1 '(cart [:a :b :c] '(1 2 3)))
; (clojure.core/for [G__4356 [:a :b :c]
; G__4357 (quote (1 2 3))]
; (clojure.core/list G__4356 G__4357))
(cart [:a :b :c] '(1 2 3))
; ((:a 1) (:a 2) (:a 3) (:b 1) (:b 2) (:b 3) (:c 1) (:c 2) (:c 3))
Essentially, you have the compiler generate the appropriate for comprehension for you. Converting this to a function is pretty straightforward, but there is a small catch:
(defn cart [& lists]
(let [syms (for [_ lists] (gensym))]
(eval `(for [~#(mapcat #(list %1 `'~%2) syms lists)]
(list ~#syms)))))
(cart [:a :b :c] '(1 2 3))
; ((:a 1) (:a 2) (:a 3) (:b 1) (:b 2) (:b 3) (:c 1) (:c 2) (:c 3))
Lists that are left unquoted are treated as function calls, which is why quoting %2 is necessary here.
Online Demo:
; https://projecteuler.net/problem=205
(defn cart [& lists]
(let [syms (for [_ lists] (gensym))]
(eval `(for [~#(mapcat #(list %1 `'~%2) syms lists)]
(list ~#syms)))))
(defn project-euler-205 []
(let [rolls (fn [n d]
(->> (range 1 (inc d))
(repeat n)
(apply cart)
(map #(apply + %))
frequencies))
peter-rolls (rolls 9 4)
colin-rolls (rolls 6 6)
all-results (* (apply + (vals peter-rolls))
(apply + (vals colin-rolls)))
peter-wins (apply + (for [[pk pv] peter-rolls
[ck cv] colin-rolls
:when (> pk ck)]
(* pv cv)))]
(/ peter-wins all-results)))
(println (project-euler-205)) ; 48679795/84934656
Personally, I would use amalloy's for solution. My general rule of thumb is that if my loop can be expressed as a single map/filter/etc call with a simple function argument (so a function name or short fn/#() form), its better to use the function. As soon as it gets more complex than that, a for expression is far easier to read. In particular, for is far better than nested maps. That said, if I didn't use for here, this is how I'd write the function:
(defn cart
([] '(()))
([xs & more]
(mapcat #(map (partial cons %)
(apply cart more))
xs)))
Things to note: First, there's no need for the reduce. Recursion can handle it just fine.
Second, only two cases. We can call the function just fine on an empty list, so all we care about is empty vs non-empty.
Third, as amalloy explained, the correct value of (cart) is '(()). This is actually rather subtle, and I reliably mess this up when I write a function like this. If you walk through a simple case very carefully, you should be able to see why that value makes the recursion work.
Fourth, I generally don't like to use fn. This is more of a personal preference, but I always use #(), partial, or comp if I can get away with it. #() is definitely idiomatic for smaller functions, though the other two are a bit less common.
Fifth, some style notes. The biggest issue is indentation. The best suggestion here is to find an editor that auto-indents lisp code. Auto-indentation is one of the most important things for your editor to provide, since it makes it blindingly obvious when your parens don't match up. Also, closing parens never go on their own line, fns don't need internal names unless you are planning on recursing, and I generally have a few more newlines than you do. I like to think that my code above is reasonably decently styled, and as another example, here is how I would format your code:
(defn cart
([] '())
([l1] (map list l1))
([l1 l2]
(map (fn [x]
(map (fn [y]
(list x y))
l2))
l1)))
(defn cartesian-product [& lists]
(reduce cart lists))
For most purposes Alan's answer is great as you get a lazy comprehension, and a lazy seq will not cause a stack overflow as you realize its members, even if you do not use (recur).
I was interested in trying to craft the tail recursive version with explicit recur, not the least of which because laziness wasn't going to be of any help in my application, but also for fun and giggles:
(defn cartesian-product
([cols] (cartesian-product '([]) cols))
([samples cols]
(if (empty? cols)
samples
(recur (mapcat #(for [item (first cols)]
(conj % item)) samples)
(rest cols)))))
My answer to this problem feels too much like these solutions in C.
Does anyone have any advice to make this more lispy?
(use 'clojure.test)
(:import 'java.lang.Math)
(with-test
(defn find-triplet-product
([target] (find-triplet-product 1 1 target))
([a b target]
(let [c (Math/sqrt (+ (* a a) (* b b)))]
(let [sum (+ a b c)]
(cond
(> a target) "ERROR"
(= sum target) (reduce * (list a b (int c)))
(> sum target) (recur (inc a) 1 target)
(< sum target) (recur a (inc b) target))))))
(is (= (find-triplet-product 1000) 31875000)))
The clojure-euluer-project has several programs for you to reference.
I personally used this algorithm(which I found described here):
(defn generate-triple [n]
(loop [m (inc n)]
(let [a (- (* m m) (* n n))
b (* 2 (* m n)) c (+ (* m m) (* n n)) sum (+ a b c)]
(if (>= sum 1000)
[a b c sum]
(recur (inc m))))))
Seems to me much less complicated :-)
In a Clojure program, I have a sequence of numbers:
(2 3 4 6 8 1)
I want to find the longest sub-sequence where the items are sequential:
(2 3 4)
I am assuming that it will involve (take-while ...) or (reduce ...).
Any ideas?
Clarification: I need the longest initial list of sequential items. Much easier, I'm sure. Thanks for the solutions to the more difficult problem I initially posed.
If you are only interested in the longest initial sequence, it's a 1-liner:
(defn longest-initial-sequence [[x :as s]]
(take-while identity (map #(#{%1} %2) s (iterate inc x))))
Taking into account the OP's comment on the question -- which completely changes the game! -- this can be written very simply:
(let [doubletons (partition 2 1 [1 2 3 5 6])
increment? (fn increment? [[x y]]
(== (inc x) y))]
(cons (ffirst doubletons)
(map second (take-while increment? doubletons))))
;; returns (1 2 3)
Note that this is actually lazy. I expect it not to hold onto the head of doubletons thanks to locals clearing. Another version:
(cons (first [1 2 3 5 6])
(map second (take-while increment? (partition 2 1 [1 2 3 5 6]))))
The original version of the question is more fun, though! :-) A super-simple solution to that could be built using the above, but of course that would be significantly less performant than using reduce. I'll see if I have anything substantially different from zmila's and dnolen's solutions -- and yet still reasonably performant -- to add to that part of this thread later. (Not very likely, I guess.)
Answer to original:
(defn conj-if-sequential
([] [])
([a] a)
([a b] (let [a (if (vector? a) a [a])]
(if (= (inc (last a)) b)
(conj a b)
a))))
(reduce conj-if-sequential [2 3 4 6 8 1])
A more generic solution for those interested:
(defn sequential-seqs
([] [])
([a] a)
([a b] (let [n (last (last a))]
(if (and n (= (inc n) b))
(update-in a [(dec (count a))] conj b)
(conj a [b])))))
(defn largest
([] nil)
([a] a)
([a b] (if (> (count b) (count a)) b a)))
(reduce largest (reduce sequential-seqs [] [2 3 4 6 8 1 4 5 6 7 8 9 13]))
I think this is much better.
(defn find-max-seq [lst]
(let [[f & r] lst,
longest-seq (fn [a b] (if (> (count a) (count b)) a b)),
[last-seq max-seq] (reduce
(fn [ [[prev-num & _ :as cur-seq] max-seq] cur-num ]
(if (== (inc prev-num) cur-num)
[(conj cur-seq cur-num) max-seq]
[(list cur-num) (longest-seq cur-seq max-seq)]
))
[(list f) ()]
r)]
(reverse (longest-seq last-seq max-seq))))
(find-max-seq '(2 3 4 6 8 1)) ; ==> (2 3 4)
(find-max-seq '(3 2 3 4 6 8 9 10 11)) ; ==> (8 9 10 11)