Why is this lazy-sequence not printing? - clojure

I cannot figure out why this lazy-sequence is not printing. I've looked at other posts on here (such as this) and none seem to be exactly what I am looking for. Here is the code segment...
(defn exp [x n]
(reduce * (repeat n x))
)
(defn primes
([] (primes 1 1))
([n m] (if (= n 1) (lazy-seq (cons (* (exp 7 n) (exp 11 m)) (primes (+ m 1) (1))))
(lazy-seq (cons (* (exp 7 n) (exp 11 m)) (primes (- n 1) (+ m 1)))))
)
)
(take 4 (primes))
Any help is greatly appreciated. Thank you!

The three comments really give the answer. But always good to actually see the code, so here are two ways that give the printed output.
(defn exp [x n]
(reduce * (repeat n x)))
(defn primes
([] (primes 1 1))
([n m] (if (= n 1)
(lazy-seq (cons (* (exp 7 n) (exp 11 m)) (primes (+ m 1) 1)))
(lazy-seq (cons (* (exp 7 n) (exp 11 m)) (primes (- n 1) (+ m 1)))))))
(defn x-1 []
(doseq [prime (take 4 (primes 2 2))]
(println prime)))
(defn x-2 []
(->> (primes 2 2)
(take 4)
(apply println)))

Related

How to return a lazy sequence from a loop recur with a conditional in Clojure?

Still very new to Clojure and programming in general so forgive the stupid question.
The problem is:
Find n and k such that the sum of numbers up to n (exclusive) is equal to the sum of numbers from n+1 to k (inclusive).
My solution (which works fine) is to define the following functions:
(defn addd [x] (/ (* x (+ x 1)) 2))
(defn sum-to-n [n] (addd(- n 1)))
(defn sum-to-k [n=1 k=4] (- (addd k) (addd n)))
(defn is-right[n k]
(= (addd (- n 1)) (sum-to-k n k)))
And then run the following loop:
(loop [n 1 k 2]
(cond
(is-right n k) [n k]
(> (sum-to-k n k) (sum-to-n n) )(recur (inc n) k)
:else (recur n (inc k))))
This only returns one answer but if I manually set n and k I can get different values. However, I would like to define a function which returns a lazy sequence of all values so that:
(= [6 8] (take 1 make-seq))
How do I do this as efficiently as possible? I have tried various things but haven't had much luck.
Thanks
:Edit:
I think I came up with a better way of doing it, but its returning 'let should be a vector'. Clojure docs aren't much help...
Heres the new code:
(defn calc-n [n k]
(inc (+ (* 2 k) (* 3 n))))
(defn calc-k [n k]
(inc (+ (* 3 k)(* 4 n))))
(defn f
(let [n 4 k 6]
(recur (calc-n n k) (calc-k n k))))
(take 4 (f))
Yes, you can create a lazy-seq, so that the next iteration will take result of the previous iteration. Here is my suggestion:
(defn cal [n k]
(loop [n n k k]
(cond
(is-right n k) [n k]
(> (sum-to-k n k) (sum-to-n n) )(recur (inc n) k)
:else (recur n (inc k)))))
(defn make-seq [n k]
(if-let [[n1 k1] (cal n k)]
(cons [n1 k1]
(lazy-seq (make-seq (inc n1) (inc k1))))))
(take 5 (make-seq 1 2))
;;=> ([6 8] [35 49] [204 288] [1189 1681] [6930 9800])
just generating lazy seq of candidatess with iterate and then filtering them should probably be what you need:
(def pairs
(->> [1 2]
(iterate (fn [[n k]]
(if (< (sum-to-n n) (sum-n-to-k n k))
[(inc n) k]
[n (inc k)])))
(filter (partial apply is-right))))
user> (take 5 pairs)
;;=> ([6 8] [35 49] [204 288] [1189 1681] [6930 9800])
semantically it is just like manually generating a lazy-seq, and should be as efficient, but this one is probably more idiomatic
If you don't feel like "rolling your own", here is an alternate solution. I also cleaned up the algorithm a bit through renaming/reformating.
The main difference is that you treat your loop-recur as an infinite loop inside of the t/lazy-gen form. When you find a value you want to keep, you use the t/yield expression to create a lazy-sequence of outputs. This structure is the Clojure version of a generator function, just like in Python.
(ns tst.demo.core
(:use tupelo.test )
(:require [tupelo.core :as t] ))
(defn integrate-to [x]
(/ (* x (+ x 1)) 2))
(defn sum-to-n [n]
(integrate-to (- n 1)))
(defn sum-n-to-k [n k]
(- (integrate-to k) (integrate-to n)))
(defn sums-match[n k]
(= (sum-to-n n) (sum-n-to-k n k)))
(defn recur-gen []
(t/lazy-gen
(loop [n 1 k 2]
(when (sums-match n k)
(t/yield [n k]))
(if (< (sum-to-n n) (sum-n-to-k n k))
(recur (inc n) k)
(recur n (inc k))))))
with results:
-------------------------------
Clojure 1.10.1 Java 13
-------------------------------
(take 5 (recur-gen)) => ([6 8] [35 49] [204 288] [1189 1681] [6930 9800])
You can find all of the details in the Tupelo Library.
This first function probably has a better name from math, but I don't know math very well. I'd use inc (increment) instead of (+ ,,, 1), but that's just personal preference.
(defn addd [x]
(/ (* x (inc x)) 2))
I'll slightly clean up the spacing here and use the dec (decrement) function.
(defn sum-to-n [n]
(addd (dec n)))
(defn sum-n-to-k [n k]
(- (addd k) (addd n)))
In some languages predicates, functions that return booleans,
have names like is-odd or is-whatever. In clojure they're usually
called odd? or whatever?.
The question-mark is not syntax, it's just part of the name.
(defn matching-sums? [n k]
(= (addd (dec n)) (sum-n-to-k n k)))
The loop special form is kind of like an anonymous function
for recur to jump back to. If there's no loop form, recur jumps back
to the enclosing function.
Also, dunno what to call this so I'll just call it f.
(defn f [n k]
(cond
(matching-sums? n k) [n k]
(> (sum-n-to-k n k) (sum-to-n n)) (recur (inc n) k)
:else (recur n (inc k))))
(comment
(f 1 2) ;=> [6 8]
(f 7 9) ;=> [35 49]
)
Now, for your actual question. How to make a lazy sequence. You can use the lazy-seq macro, like in minhtuannguyen's answer, but there's an easier, higher level way. Use the iterate function. iterate takes a function and a value and returns an infinite sequence of the value followed by calling the function with the value, followed by calling the function on that value etc.
(defn make-seq [init]
(iterate (fn [n-and-k]
(let [n (first n-and-k)
k (second n-and-k)]
(f (inc n) (inc k))))
init))
(comment
(take 4 (make-seq [1 2])) ;=> ([1 2] [6 8] [35 49] [204 288])
)
That can be simplified a bit by using destructuring in the argument-vector of the anonymous function.
(defn make-seq [init]
(iterate (fn [[n k]]
(f (inc n) (inc k)))
init))
Edit:
About the repeated calculations in f.
By saving the result of the calculations using a let, you can avoid calculating addd multiple times for each number.
(defn f [n k]
(let [to-n (sum-to-n n)
n-to-k (sum-n-to-k n k)]
(cond
(= to-n n-to-k) [n k]
(> n-to-k to-n) (recur (inc n) k)
:else (recur n (inc k)))))

Getting the most nested list in Clojure

I am migrating some LISP functions to Clojure. I have problems with StackOverflow message for the following functions:
(defn m
[list depth]
(cond
(= list nil) depth
(atom (first list)) (m (rest list) depth)
(> (m (first list) (+ depth 1)) (m (rest list) depth)) (m (first list) (+ depth 1))
:default (m (rest list) depth))
)
(defn n
[list depth maxdepth]
(cond
(= list nil) nil
(= depth maxdepth) list
(atom (first list)) (n (rest list) depth maxdepth)
(= 0 (n (first list) (+ depth 1) maxdepth)) (n (last list) depth maxdepth)
:default (n (first list) (+ depth 1) maxdepth))
)
(defn myfind[mylist]
(n mylist 0 (m mylist 0))
)
What I basically want is the output of the most nested list, as in:
(myfind '(1 2 3 (4 5) 6 ((7 8) 9)))
=> (7 8)
The goal is to use recursion and minimize the usage of builtin functions to achieve that.
What is wrong in this case?
(defn- deepest-with-depth [depth s]
(let [nested-colls (filter coll? s)]
(if (seq nested-colls)
(mapcat (partial deepest-with-depth (inc depth)) nested-colls)
[[depth s]])))
(defn deepest [s]
(->> (deepest-with-depth 0 s)
(apply max-key first)
second))
> (deepest '(1 2 3 (4 5) 6 ((7 8) 9)))
(7 8)
Feel free to subsitute some function calls (e.g. max-key, partial) with their implementations, if they conflict with your requirements.
here is one more variant, with just classic old school solution, and no clojure specific sequence functions at all:
(defn deepest [items depth]
(if (sequential? items)
(let [[it1 d1 :as res1] (deepest (first items) (inc depth))
[it2 d2 :as res2] (deepest (next items) depth)]
(cond (>= depth (max d1 d2)) [items depth]
(>= d1 d2) res1
:else res2))
[items -1]))
it is also notable by it's classic approach to the nested lists recursion: first you recur on car, then on cdr, and then combine these results.
user> (deepest '(1 2 3 (4 5) 6 ((7 8) 9)) 0)
[(7 8) 2]
user> (deepest '(1 2 3 (4 5) 6) 0)
[(4 5) 1]
user> (deepest '(1 2 3 (x ((y (z)))) (4 5) 6) 0)
[(z) 4]
user> (deepest '(1 2 3 (x ((y (z)))) (4 5 ((((((:xxx)))))))) 0)
[(:xxx) 7]
user> (deepest '(1 2 3 ((((((((nil)))))))) (x ((y (z)))) (4 5) 6) 0)
[(nil) 8]
user> (deepest '(1 2 3) 0)
[(1 2 3) 0]
(defn- max-depth-entry [a-list]
(let [sub-lists (filter coll? a-list)
[depth list] (if (empty? sub-lists)
[0 a-list]
(apply max-key first (map max-depth-entry sub-lists)))]
[(inc depth) list]))
(max-depth-entry '(1 2 3 (4 5) 6 ((7 8) 9)))
;[3 (7 8)]
Then
(def max-depth-sublist (comp second max-depth-entry))
(max-depth-sublist '(1 2 3 (4 5) 6 ((7 8) 9)))
;(7 8)
I owe the idea of using max-key to OlegTheCat's answer. I originally knitted my own, using reduce:
(defn- max-depth-entry [a-list]
(let [sub-lists (filter coll? a-list)
[a-list a-depth] (reduce
(fn ([] [a-list 0])
([[as an :as asn] [s n :as sn]] (if (> n an) sn asn)))
(map max-depth-entry sub-lists))]
[a-list (inc a-depth)]))
Then
(def max-depth-sublist (comp first max-depth-entry))
Now I'm ready to return to Sequs Horribilis on 4Clojure, which has stymied me until now.

NullPointerException using Clojure

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))))

Trapezoidal Integration is not accurate enough in Clojure

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

Project Euler #9 (Pythagorean triplets) in Clojure

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 :-)