Unobtrusive Way to Trim Cycle in Clojure Sequence - clojure

I am trying to write a lazy seq to generate the Collatz sequence for a given input int.
I love this function because is so cleanly maps to the mathematical definition:
(defn collatz
"Returns a lazy seq of the Collatz sequence starting at n and ending at 1 (if
ever)."
[n]
(letfn [(next-term [x]
(if (even? x)
(/ x 2)
(inc (* 3 x))))]
(iterate next-term n)))
The problem is that this produces infinite seqs because of how the Collatz sequence behaves:
(take 10 (collatz 5))
=> (5 16 8 4 2 1 4 2 1 4)
I could easily drop the cycle by adding (take-while #(not= 1 %) ...), but the 1 is part of the sequence. All the other ways I've thought to trim the cycle after the one are ugly and obfuscate the mathematical heart of the Collatz sequence.
(I've considered storing the seen values in an atom and using that in a take-while predicate, or just storing a flag in an atom to similar effect. But I feel like there is some better, more beautiful, less intrusive way to do what I want here.)
So my question: What are clean ways to detect and trim cycles in infinite seqs? Or, could I generate my lazy seq in a way (perhaps using for) that automatically trims when it reaches 1 (inclusive)?

The below looks like a more or less literal translation of the definition and gives the result you want:
(defn collatz-iter [x]
(cond (= x 1) nil
(even? x) (/ x 2)
:else (inc (* 3 x))))
(defn collatz [n]
(take-while some? (iterate collatz-iter n)))
(collatz 12) ;; => (12 6 3 10 5 16 8 4 2 1)
Basically, you can use nil as the value to stop the sequence, thus keeping the final 1.

you could also use another approach, which is recursive lazy-seq generation. That is quite common for this class of tasks, doesn't break the lazy sequence abstraction and avoids intermediate sequences' creation:
(defn collatz [n]
(if (== n 1)
(list 1)
(lazy-seq (cons n (collatz (if (even? n)
(/ n 2)
(inc (* 3 n))))))))
user> (collatz 12)
;;=> (12 6 3 10 5 16 8 4 2 1)

Related

Re-implementing Partition in clojure

I am trying to find a method to implement Partition (with [] padding) in clojure. I think it's doable using loop and recur and mapping it into the list:
(defn collect-h [v n]
(loop [i n
res []
lst v
]
(if (= 0 i)
res
(recur (dec i) (cons (first lst) res) (next lst))
)
)
)
So the problem is that implementation only works on the first series of answer "(collect-h [1 2 3 4 5 6 7 8 9 10] 3) will give ((1 2 3))". So I need to map it to the whole collection and remove the first n number in every loop, but that doesn't look really efficient. I wonder if there is a better way to solve it.
Edit:
so it should work like this:
(collect-h [1 2 3 4 5 6 7 8 9 10] 3) ;; ((1 2 3) (4 5 6) (7 8 9) (10))
which is same to
(partition 3 3 [] [1 2 3 4 5 6 7 8 9 10])
#Timothy-Pratley answer is nice, but it is not tail recursive, meaning that it would cause stack overflow in case of large collection. Here is non stack consuming variant:
(defn my-partition [n items]
(loop [res [] items items]
(if (empty? items)
res
(recur (conj res (take n items))
(drop n items)))))
user> (my-partition 3 (range 10))
[(0 1 2) (3 4 5) (6 7 8) (9)]
Building off #Timothy-Pratley and the Clojure source code, you could also use lazy-seq:
(defn partition-ghetto [n xs]
(lazy-seq (when-let [s (seq xs)]
(cons (take n s) (partition-ghetto n (drop n s))))))
How about this?
(defn partition-ghetto [n xs]
(if (seq xs)
(cons (take n xs) (partition-ghetto n (drop n xs)))
()))
(partition-ghetto 3 (range 10))
=> ((0 1 2) (3 4 5) (6 7 8) (9))
Definitely not as good as the core version, but might provide some ideas?
Note that this recursive definition is not tail recursive, so will blow the stack for large sequences, nor is it lazy like most Clojure sequence functions. The advantage of laziness on sequences is that you are neither stack nor heap bound when operating on a stream. See alternative answers below that provide solutions to these concerns.

clojure laziness: prevent unneded mapcat results to realize

Consider a query function q that returns, with a delay, some (let say ten) results.
Delay function:
(defn dlay [x]
(do
(Thread/sleep 1500)
x))
Query function:
(defn q [pg]
(lazy-seq
(let [a [0 1 2 3 4 5 6 7 8 9 ]]
(println "q")
(map #(+ (* pg 10) %) (dlay a)))))
Wanted behaviour:
I would like to produce an infinite lazy sequence such that when I take a value only needed computations are evaluated
Wrong but explicative example:
(drop 29 (take 30 (mapcat q (range))))
If I'm not wrong, it needs to evaluate every sequence because it really doesn't now how long the sequences will be.
How would you obtain the correct behaviour?
My attempt to correct this behaviour:
(defn getq [coll n]
(nth
(nth coll (quot n 10))
(mod n 10)))
(defn results-seq []
(let [a (map q (range))]
(map (partial getq a)
(iterate inc 0)))) ; using iterate instead of range, this way i don't have a chunked sequence
But
(drop 43 (take 44 (results-seq)))
still realizes the "unneeded" q sequences.
Now, I verified that a is lazy, iterate and map should produce lazy sequences, so the problem must be with getq. But I can't understand really how it breaks my laziness...perhaps does nth realize things while walking through a sequence? If this would be true, is there a viable alternative in this case or my solution suffers from bad design?

find all subsets of an integer collection that sums to n

i'm trying to find a function that, given S a set of integer and I an integer, return all the subsets of S that sum to I
is there such a function somewhere in clojure-contrib or in another library ?
if no, could anyone please give me some hints to write it the clojure way?
Isn't this the subset sum problem, a classic NP-complete problem?
In which case, I'd just generate every possible distinct subset of S, and see which subsets sums to I.
I think it is the subset sum problem, as #MrBones suggests. Here's a brute force attempt using https://github.com/clojure/math.combinatorics (lein: [org.clojure/math.combinatorics "0.0.7"]):
(require '[clojure.math.combinatorics :as c])
(defn subset-sum [s n]
"Return all the subsets of s that sum to n."
(->> (c/subsets s)
(filter #(pos? (count %))) ; ignore empty set since (+) == 0
(filter #(= n (apply + %)))))
(def s #{1 2 45 -3 0 14 25 3 7 15})
(subset-sum s 13)
; ((1 -3 15) (2 -3 14) (0 1 -3 15) (0 2 -3 14) (1 2 3 7) (0 1 2 3 7))
(subset-sum s 0)
; ((0) (-3 3) (0 -3 3) (1 2 -3) (0 1 2 -3))
These "subsets" are just lists. Could convert back to sets, but I didn't bother.
You can generate the subsets of a set like this:
(defn subsets [s]
(if (seq s)
(let [f (first s), srs (subsets (disj s f))]
(concat srs (map #(conj % f) srs)))
(list #{})))
The idea is to choose an element from the set s: the first, f, will do. Then we recursively find the subsets of everything else, srs. srs comprises all the subsets without f. By adding f to each of them, we get all the subsets with f. And together, that's the lot. Finally, if we can't choose an element because there aren't any, the only subset is the empty one.
All that remains to do is to filter out from all the subsets the ones that sum to n. A function to test this is
(fn [s] (= n (reduce + s)))
It is not worth naming.
Putting this together, the function we want is
(defn subsets-summing-to [s n]
(filter
(fn [xs] (= n (reduce + xs)))
(subsets s)))
Notes
Since the answer is a sequence of sets, we can make it lazier by changing concat into lazy-cat. map is lazy anyway.
We may appear to be generating a lot of sets, but remember that they share storage: the space cost of keeping another set differing by a single element is (almost) constant.
The empty set sums to zero in Clojure arithmetic.

repeatedly apply a function until test no longer yields true

I wrote this code to nest a function n times and am trying to extend the code to handle a test. Once the test returns nil the loop is stopped. The output be a vector containing elements that tested true. Is it simplest to add a while loop in this case? Here is a sample of what I've written:
(defn nester [a inter f]
(loop [level inter expr a]
(if (= level 0) expr
(if (> level 0) (recur (dec level) (f expr))))))
An example input would be an integer 2, and I want to nest the inc function until the output is great than 6. The output should be [2 3 4 5 6 7].
(defn nester [a inter f test-fn]
(loop [level inter
expr a]
(if (or (zero? level)
(nil? (test-fn expr)))
expr
(recur (dec level)
(f expr)))))
If you also accept false (additionally to nil) from your test-fn, you could compose this more lazily:
(defn nester [a inter f test-fn]
(->> (iterate f a)
(take (inc inter))
(drop-while test-fn)
first))
EDIT: The above was answered to your initial question. Now that you have specified completely changed the meaning of your question:
If you want to generate a vector of all iterations of a function f over a value n with a predicate p:
(defn nester [f n p]
(->> (iterate f n)
(take-while p)
vec))
(nester inc 2 (partial > 8)) ;; predicate "until the output is greater than six"
;; translated to "as long as 8 is greater than
;; the output"
=> [2 3 4 5 6 7]
To "nest" or iterate a function over a value, Clojure has the iterate function. For example, (iterate inc 2) can be thought of as an infinite lazy list [2, (inc 2), (inc (inc 2)), (inc (inc (inc 2))) ...] (I use the [] brackets not to denote a "list"--in fact, they represent a "vector" in Clojure terms--but to avoid confusion with () which can denote a data list or an s-expression that is supposed to be a function call--iterate does not return a vector). Of course, you probably don't want an infinite list, which is where the lazy part comes in. A lazy list will only give you what you ask it for. So if you ask for the first ten elements, that's what you get:
user> (take 10 (iterate inc 2))
> (2 3 4 5 6 7 8 9 10 11)
Of course, you could try to ask for the whole list, but be prepared to either restart your REPL, or dispatch in a separate thread, because this call will never end:
user> (iterate inc 2)
> (2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
=== Shutting down REPL ===
=== Starting new REPL at C:\Users\Omnomnomri\Clojure\user ===
Clojure 1.5.0
user>
Here, I'm using clooj, and this is what it looks like when I restart my REPL. Anyways, that's all just a tangent. The point is that iterate answers the core of your question. The other part, stopping upon some test condition, involves take-while. As you might imagine, take-while is a lot like take, only instead of stopping after some number of elements, it stops upon some test condition (or in Clojure parlance, a predicate):
user> (take-while #(< % 10) (iterate inc 2))
> (2 3 4 5 6 7 8 9)
Note that take-while is exclusive with its predicate test, so that here once the value fails the test (of being less than 10), it excludes that value, and only includes the previous values in the return result. At this point, solving your example is pretty straightfoward:
user> (take-while #(< % 7) (iterate inc 2))
> (2 3 4 5 6)
And if you need it to be a vector, wrap the whole thing in a call to vec:
user> (vec (take-while #(< % 7) (iterate inc 2)))
> [2 3 4 5 6]

Cleaning up Clojure function

Coming from imperative programming languages, I am trying to wrap my head around Clojure in hopes of using it for its multi-threading capability.
One of the problems from 4Clojure is to write a function that generates a list of Fibonacci numbers of length N, for N > 1. I wrote a function, but given my limited background, I would like some input on whether or not this is the best Clojure way of doing things. The code is as follows:
(fn fib [x] (cond
(= x 2) '(1 1)
:else (reverse (conj (reverse (fib (dec x))) (+ (last (fib (dec x))) (-> (fib (dec x)) reverse rest first))))
))
The most idiomatic "functional" way would probably be to create an infinite lazy sequence of fibonacci numbers and then extract the first n values, i.e.:
(take n some-infinite-fibonacci-sequence)
The following link has some very interesting ways of generating fibonnaci sequences along those lines:
http://en.wikibooks.org/wiki/Clojure_Programming/Examples/Lazy_Fibonacci
Finally here is another fun implementation to consider:
(defn fib [n]
(let [next-fib-pair (fn [[a b]] [b (+ a b)])
fib-pairs (iterate next-fib-pair [1 1])
all-fibs (map first fib-pairs)]
(take n all-fibs)))
(fib 6)
=> (1 1 2 3 5 8)
It's not as concise as it could be, but demonstrates quite nicely the use of Clojure's destructuring, lazy sequences and higher order functions to solve the problem.
Here is a version of Fibonacci that I like very much (I took the implementation from the clojure wikibook: http://en.wikibooks.org/wiki/Clojure_Programming)
(def fib-seq (lazy-cat [0 1] (map + (rest fib-seq) fib-seq)))
It works like this: Imagine you already have the infinite sequence of Fibonacci numbers. If you take the tail of the sequence and add it element-wise to the original sequence you get the (tail of the tail of the) Fibonacci sequence
0 1 1 2 3 5 8 ...
1 1 2 3 5 8 ...
-----------------
1 2 3 5 8 13 ...
thus you can use this to calculate the sequence. You need two initial elements [0 1] (or [1 1] depending on where you start the sequence) and then you just map over the two sequences adding the elements. Note that you need lazy sequences here.
I think this is the most elegant and (at least for me) mind stretching implementation.
Edit: The fib function is
(defn fib [n] (nth fib-seq n))
Here's one way of doing it that gives you a bit of exposure to lazy sequences, although it's certainly not really an optimal way of computing the Fibonacci sequence.
Given the definition of the Fibonacci sequence, we can see that it's built up by repeatedly applying the same rule to the base case of '(1 1). The Clojure function iterate sounds like it would be good for this:
user> (doc iterate)
-------------------------
clojure.core/iterate
([f x])
Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects
So for our function we'd want something that takes the values we've computed so far, sums the two most recent, and returns a list of the new value and all the old values.
(fn [[x y & _ :as all]] (cons (+ x y) all))
The argument list here just means that x and y will be bound to the first two values from the list passed as the function's argument, a list containing all arguments after the first two will be bound to _, and the original list passed as an argument to the function can be referred to via all.
Now, iterate will return an infinite sequence of intermediate values, so for our case we'll want to wrap it in something that'll just return the value we're interested in; lazy evaluation will stop the entire infinite sequence being evaluated.
(defn fib [n]
(nth (iterate (fn [[x y & _ :as all]] (cons (+ x y) all)) '(1 1)) (- n 2)))
Note also that this returns the result in the opposite order to your implementation; it's a simple matter to fix this with reverse of course.
Edit: or indeed, as amalloy says, by using vectors:
(defn fib [n]
(nth (iterate (fn [all]
(conj all (->> all (take-last 2) (apply +)))) [1 1])
(- n 2)))
See Christophe Grand's Fibonacci solution in Programming Clojure by Stu Halloway. It is the most elegant solution I have seen.
(defn fibo [] (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])))
(take 10 (fibo))
Also see
How can I generate the Fibonacci sequence using Clojure?