How to generate a lazy sequence in clojure using non-tail recursion? - recursion

Take integer partition problem for example, I can write the following code to output all partitions of a positive integer n:
(defn foo
([n] (foo n n []))
([n k buf]
(if (zero? n)
(println buf)
(doseq [i (range 1 (inc (min n k)))]
(foo (- n i) i (conj buf i))))))
Then (foo 5) outputs:
[1 1 1 1 1]
[2 1 1 1]
[2 2 1]
[3 1 1]
[3 2]
[4 1]
[5]
The question is how could I write a function bar which generates a lazy-seq containing such results? For example, I want (bar 5) generates ([1 1 1 1 1] [2 1 1 1] [2 2 1] [3 1 1] [3 2] [4 1] [5]).

Here is a roughly equivalent function generating the partitions as a sequence of sequences:
(defn bar
([n] (bar n n))
([n k]
(if (zero? n)
[[]]
(for [i (range 1 (inc (min n k))), tail (bar (- n i) i)]
(cons i tail)))))
For example,
(bar 5)
; ((1 1 1 1 1) (2 1 1 1) (2 2 1) (3 1 1) (3 2) (4 1) (5))
How lazy is bar?
for is lazy.
to make it lazier, wrap the body in a lazy-seq.
I have my doubts about the above.
The function recurses to depth n.
Wrapping the body in lazy-seq I suspect just stacks up lazy
sequences, producing just as deep a recursive call stack on accessing the
first element.
Besides, the same tails are repeatedly computed; the more so since (bar n k) is the same for all k >= n.
If performance of this function is a specific concern, there are iterative algorithms with constant time per step. As #CharlesDuffy's comment implies, these can be re-jigged to produce lazy sequences.
Why gaze into the crystal ball when you can read the book?
The standard namespace clojure.math.combinatorics, hosted here, contains a partition function that produces a lazy sequence of the partitions of any sequence of objects - fast. Integer partition is where we count the elements of each partition of identical objects. They come out in reverse lexicographic order.
For example
(map #(map count %) (combo/partitions (repeat 5 :whatever)))
;((5) (4 1) (3 2) (3 1 1) (2 2 1) (2 1 1 1) (1 1 1 1 1))
No doubt the code can be stripped down to deal with just this case.

Here is recursive solution. There are some ways to optimize it and code is not the best.
(defn partitions [n]
(loop [m n
res [(init-step n m)]]
(let [l (last res)]
(if (= m 1)
res
(if (last-step? (last res))
(recur (- m 1) (vec (conj res (init-step n (- m 1)))))
(recur m (next-step res)))))))
(defn init-step [n m]
(if (= n m)
[n]
(loop [res [m (- n m)]]
(let [l (last res)
f (first res)]
(if (<= l f)
res
(recur (vec (conj (vec (butlast res)) f (- l f)))))))))
(defn next-step [res]
(let [input-vec (last res)
cnt (count input-vec)
i (.indexOf input-vec 1)
j (if (> i -1) (- i 1) (- cnt 1))
m (- cnt j)
new-vec (conj (vec (take j input-vec)) (- (input-vec j) 1))]
(conj res (vec (concat new-vec (repeat m 1))))))
(defn last-step? [input-vec]
(if
(or (nil? input-vec)
(= (count input-vec) 1)
(= (input-vec 1) 1)) true
false))
(partitions 10)
#=> [[10] [9 1] [8 2] [8 1 1] [7 3] [7 2 1] [7 1 1 1] [6 4] [6 3 1] [6 2 1 1] [6 1 1 1 1] [5 5] [5 4 1] [5 3 1 1] [5 2 1 1 1] [5 1 1 1 1 1] [4 4 2] [4 4 1 1] [4 3 1 1 1] [4 2 1 1 1 1] [4 1 1 1 1 1 1] [3 3 3 1] [3 3 2 1 1] [3 3 1 1 1 1] [3 2 1 1 1 1 1] [3 1 1 1 1 1 1 1] [2 2 2 2 2] [2 2 2 2 1 1] [2 2 2 1 1 1 1] [2 2 1 1 1 1 1 1] [2 1 1 1 1 1 1 1 1] [1 1 1 1 1 1 1 1 1 1]]

Related

How to display fibonacci sequences less than upper bound (CLISP)

I am trying to display a Fibonacci sequence less than an upper bound, but I'm having trouble printing out the series that is constrained by that upper bound.
Without using imperative programming principles with declaring variables such as setf, setq, and set, etc. How can I solve this problem?
So far I have
(defun fibonacci (n &optional (a 0) (b 1))
(if (or (zerop n) (< a n)
nil)
(cons a (fibonacci (1- n) b (+ a b)))))
Expected output of (fibonacci 100): (0 1 1 2 3 5 8 13 21 34 55 89). However, what I am getting is (0 1 1 2 3 5 8 13 21 34 55).
You are decreasing upper bound for no reason. When you remove 1- and move one ) to right place, it works as expected:
(defun fibonacci (n &optional (a 0) (b 1))
(if (or (zerop n) (> a n))
nil
(cons a (fibonacci n b (+ a b)))))
Tests:
CL-USER 4 > (fibonacci 10)
(0 1 1 2 3 5 8)
CL-USER 5 > (fibonacci 100)
(0 1 1 2 3 5 8 13 21 34 55 89)
What you meant is
(defun fibonacci (n &optional (a 0) (b 1))
(if (or (zerop n) (> a n))
nil
(cons a (fibonacci n b (+ a b)))))
You had a ) placement typo / error, and the flipped test. Also, n is the upper limit, not a count. So there's no reason to decrease it.

Clojure: Increment first element of every vector in list

I have a list of vectors like this:
([4 0] [4 2] [2 1] [4 1])
How can i increment the first element of every vector by a certain value X ?
desired output:
([5 0] [5 2] [3 1] [5 1])
This is my current approach, but i think i could be much simpler:
(defn shiftVector [oldVector number]
(map vector
(map #(+ (first %) number) oldVector )
(map #(second %) oldVector))
)
Since vectors are associative on their indices, probably the simplest approach is:
(defn shift-vector [v n]
(map #(update % 0 + n) v))
(shift-vector [[4 0] [4 2] [2 1] [4 1]] 1)
;=> ([5 0] [5 2] [3 1] [5 1])
This works with any length vectors in the list (except empty vectors but then you couldn't increment those anyway).
Extract the first element, increment it, then put everything back into a new vector:
(defn inc-first [col]
(map #(into [] (flatten (conj [] (inc (first %)) (rest %)))) col))
Tests:
user=> (inc-first '([4 0] [4 2] [2 1] [4 1]))
([5 0] [5 2] [3 1] [5 1])
user=> (inc-first '([4 0 0] [4 2 2] [2 1 1] [4 1 1]))
([5 0 0] [5 2 2] [3 1 1] [5 1 1])
user=> (inc-first '([4 4 4 4] [4 2 2 2] [2 2 3 4] [4 1 0 -1]))
([5 4 4 4] [5 2 2 2] [3 2 3 4] [5 1 0 -1])
Use map.
;this solution works only for vectors of size 2
(defn inc-lst [lst x]
(map (fn [e] (vector (+ (first e) x) (second e)))
lst))
(inc-lst '([4 0] [4 2] [2 1] [4 1]) 1)
;more general solution, works for vectors of size >= 1
(defn inc-lst2 [lst x]
(map (fn [e] (apply vector (+ (first e) x) (rest e)))
lst))
(inc-lst2 '([4 0 0] [4 2 2] [2 1 1] [4 1 1]) 1)
(inc-lst2 '([4] [4] [2] [4]) 1)

Scheme - Lagrange's four-square theorem

I try to implement a function that computes the Lagrange's four-square theorem with a natural number n in scheme. However I haven't any idea to do that... Can someone give me a example/code please?
For example, a^2 + b^2 + c^2 + d^2 = n, where n is the input of the function.
You can do this with two functions (main & auxiliary):
If n is natural, (lagrange n) gives the list of all the quadruplets (a, b, c, d) such as a^2 + b^2 + c^2 + d^2 = n.
(define lagrange
(lambda (n)
(lagrange-aux 4 0 n)))
(define lagrange-aux
(lambda (size m sum)
(cond ((and (zero? size) (zero? sum)) '(()))
((or (zero? size) (> (* m m) sum)) '())
(else (append (map (lambda (x) (cons m x))
(lagrange-aux (- size 1) 0 (- sum (* m m))))
(lagrange-aux size (+ m 1) sum))))))
Example:
(lagrange 13) ==>
((0 0 2 3) (0 0 3 2) (0 2 0 3) (0 2 3 0) (0 3 0 2) (0 3 2 0)
(1 2 2 2) (2 0 0 3) (2 0 3 0) (2 1 2 2) (2 2 1 2) (2 2 2 1)
(2 3 0 0) (3 0 0 2) (3 0 2 0) (3 2 0 0))

Using 'map' with different sized collections in clojure

I'd like to understand the idiomatic way with which to operate over collections of different sizes in clojure. Is there a way I can tell the function 'map' to pad the rest of a collection with some default value?
As an example, suppose I have 3 vectors:
(def x [1 2 3 4])
(def y [1 2 3 4 5])
(def z [1 2 3 4 5 6 7])
(map + x y z) ; yields (3 6 9 12)
In this case, how can I pad x and y with zeroes and have this yield:
(3 6 9 12 10 6 7)
map doesn't do it itself, but you can use a combination of concat and repeat to obtain the desired result:
(def x [1 2 3 4])
(def y [1 2 3 4 5])
(def z [1 2 3 4 5 6 7])
(map +
(concat x (repeat 0))
(concat y (repeat 0))
z) ; => (3 6 9 12 10 6 7)
Here's the API documentation for concat, and for repeat.
And here's a sketch of how you could abstract this away a bit, so you don't need to know which of the collections is longest. (In the snippet above, if you concat all the collections to (repeat 0) you'll have an infinite sequence).
(defn map-longest
[f default & colls]
(lazy-seq
(when (some seq colls)
(cons
(apply f (map #(if (seq %) (first %) default) colls))
(apply map-longest f default (map rest colls))))))
(map-longest +
0
[1 2 3 4]
[1 2 3 4 5]
[1 2 3 4 5 6 7]) ; => (3 6 9 12 10 6 7)
You can see a couple other approaches as answers to this previous question on Stack Overflow.
You can merge vector of maps with variable lengths by the following function:
(defn merge-maps
[& args]
(let [max-count (apply max (map #(count %1) args))
items (map #(take max-count (concat %1 (repeat nil))) args)]
(apply map merge items)))
This function makes the solution more generalized and can take any length of vector of maps.

What's the idiomatic way to map vector according to the longest seq in clojure?

(map vector [1 2 3] [4 5])
will give:
([1 4] [2 5])
Here 3 is discarded.
What if I want to pad those too short seqs to the largest length automatically?
e.g.
What's the idiomatic way if I want to get
([1 4] [2 5] [3 nil])
(defn map-all [f & colls]
(lazy-seq
(when (some seq colls)
(cons (apply f (map first colls))
(apply map-all f (map rest colls))))))
(map-all vector [1 2 3] [4 5])
;=> ([1 4] [2 5] [3 nil])

Resources