Getting the most nested list in Clojure - 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.

Related

function flatten in Clojure

When translate a function flatten from Scheme to Clojure, I have encountered
an error "Execution error (IllegalArgumentException)", Please feel free to comment.
Clojure (Encounter error)
(defn flatten [x]
(cond
(empty? x) '()
(not (coll? x)) (list x)
:else (conj (flatten (first x)) (flatten (rest x)))))
(flatten '((1) 2 ((3 4) 5) ((())) (((6))) 7 8 ()))
Scheme
> (define (flatten x)
(cond ((null? x) '())
((not (pair? x)) (list x))
(else (append (flatten (car x))
(flatten (cdr x))))))
> (flatten '((1) 2 ((3 4) 5) ((())) (((6))) 7 8 ()))
(1 2 3 4 5 6 7 8)
Here is an implementation that works for me
(defn flatten [x]
(cond
(not (coll? x)) (list x)
(empty? x) '()
:else (concat (flatten (first x)) (flatten (rest x)))))
(comment
(flatten '((1) 2 ((3 4) 5) ((())) (((6))) 7 8 ())))
;returns (1 2 3 4 5 6 7 8)
The only difference is that I put first the (not (coll? x)) and then the empty? (because (empty? 3) will throw an error)
The other change is the concat instead of conj. I don't think it's recommended to use concat because it can throw a Stack Overflow Error (see : https://stuartsierra.com/2015/04/26/clojure-donts-concat) but it works in this case ...
One more version, based on Alan Thompson's solution:
(defn flat [data]
(reduce (fn [result e]
(if (not (sequential? e))
(conj result e)
(into result (flat e))))
[] data))
Tests:
(clojure.test/are [result arg]
(= result (flat arg))
[1 2 3] [1 2 3]
[1 2 3] [1 [2 3]]
[1 2 3] [1 [2 [3]]]
[0 1 2 3 4 5 6 7] [[0] [1 2 3] [4 5 [6 7]]])
=> true
Here is an alternate version that may be a bit more straightforward:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(defn flatten
[data]
(loop [result []
items data]
(if (empty? items)
result
(let [item (first items)
items-next (rest items)]
(if (not (sequential? item))
(recur
(conj result item)
items-next)
(recur
(into result (flatten item))
items-next))))))
(dotest
(is= (flatten [1 2 3]) [1 2 3])
(is= (flatten [1 [2 3]]) [1 2 3])
(is= (flatten [1 [2 [3]]]) [1 2 3])
(is= (flatten [[0] [1 2 3] [4 5 [6 7]]]) [0 1 2 3 4 5 6 7])
; Cannot flatten a scalar value - we don't want (flatten 3) => [3]
(throws? (flatten 3)))
Note that we avoid tricks like wrapping every scalar value in a list, so we don't get the non-intuitive result (flatten 3) => [3].
Build using my favorite template project.

Clojure - using map recursively

If I have a list, I can use map to apply a function to each item of the list.
(map sqrt (list 1 4 9))
(1 2 3)
I can also use map in front of a list of lists:
(map count (list (list 1 2 3) (list 4 5)))
(4 5)
Now is there a way to apply sqrt to each number in the list of lists? I want to start from
(list (list 1 4 9) (list 16 25))
and obtain
((1 2 3)(4 5))
However, the following does not seem to work,
(map (map sqrt) (list (list 1 4 9) (list 16 25)))
nor the following.
(map (fn [x] (map sqrt x)) (list (list 1 4 9) (list 16 25)))
Why? (And how do I solve this?)
Your second to last version "nearly" works. Clojure has no automatic
currying, so (map sqrt) is not partial application, but (map sqrt)
returns a transducer, which takes one argument and returns a function
with three different arities - so running your code there will give you
back a function for each list of numbers.
To make that work, you can use partial:
user=> (map (partial map sqrt) (list (list 1 4 9) (list 16 25)))
((1 2 3) (4 5))
And of course there is the obligatory specter answer:
user=> (transform [ALL ALL] sqrt '((1 4 9)(16 25)))
((1 2 3) (4 5))
You can write recursive function for this task:
(defn deep-map [f seq1]
(cond (empty? seq1) nil
(sequential? (first seq1))
(cons (deep-map f (first seq1))
(deep-map f (rest seq1)))
:else (cons (f (first seq1))
(deep-map f (rest seq1)))))
Example:
(deep-map #(Math/sqrt %) '((1 4 9) (16 25 36)))
=> ((1.0 2.0 3.0) (4.0 5.0 6.0))
Or you can use clojure.walk and function postwalk:
(clojure.walk/postwalk
#(if (number? %) (Math/sqrt %) %)
'((1 4 9) (16 25 36)))
=> ((1.0 2.0 3.0) (4.0 5.0 6.0))
The function map is closely related to the function for, which I think is sometimes easier to use. Here is how I would solve this problem:
(let [matrix [[1 4 9]
[16 25]]
result (vec (for [row matrix]
(vec (for [num row]
(Math/sqrt num)))))]
result)
with result:
result =>
[[1.0 2.0 3.0]
[4.0 5.0]]
If you remove the two (vec ...) bits, you'll see the same result but for normally returns a lazy sequence.
#MartinPuda's answer is right.
The tail call recursive version is here:
(defn map* [f sq & {:keys [acc] :or {acc '()}}]
(cond (empty? sq) (vec (reverse acc))
(sequential? (first sq)) (map* f
(rest sq)
:acc (cons (map* f (first sq)) acc))
:else (map* f (rest sq) :acc (cons (f (first sq)) acc))))
By tradition in lisp, such recursively into the nested structure going functions are fnname* (marked by an asterisk at the end).
acc accumulates the result nested tree which is constructed by cons.
In your case this would be:
(map* Math/sqrt (list (list 1 4 9) (list 16 25)))
Test with:
(map* (partial + 1) '[1 2 [3 4 [5] 6] 7 [8 [9]]])
;; => [2 3 [4 5 [6] 7] 8 [9 [10]]]

clojure split collection in chunks of increasing size

Hi I am a clojure newbie,
I am trying to create a function that splits a collection into chunks of increasing size something along the lines of
(apply #(#(take %) (range 1 n)) col)
where n is the number of chunks
example of expected output:
with n = 4 and col = (range 1 4)
(1) (2 3) (4)
with n = 7 and col = (range 1 7)
(1) (2 3) (4 5 6) (7)
You can use something like this:
(defn partition-inc
"Partition xs at increasing steps of n"
[n xs]
(lazy-seq
(when (seq xs)
(cons (take n xs)
(partition-inc (inc n) (drop n xs))))))
; (println (take 5 (partition-inc 1 (range))))
; → ((0) (1 2) (3 4 5) (6 7 8 9) (10 11 12 13 14))
Or if you want to have more influence, you could alternatively provide
a sequence for the sizes (behaves the same as above, if passed (iterate inc 1) for sizes:
(defn partition-sizes
"Partition xs into chunks given by sizes"
[sizes xs]
(lazy-seq
(when (and (seq sizes) (seq xs))
(let [n (first sizes)]
(cons (take n xs) (partition-sizes (rest sizes) (drop n xs)))))))
; (println (take 5 (partition-sizes (range 1 10 2) (range))))
; → ((0) (1 2 3) (4 5 6 7 8) (9 10 11 12 13 14 15) (16 17 18 19 20 21 22 23 24))
An eager solution would look like
(defn partition-inc [coll]
(loop [rt [], c (seq coll), n 1]
(if (seq c)
(recur (conj rt (take n c)) (drop n c) (inc n))
rt)))
another way would be to employ some clojure sequences functions:
(->> (reductions (fn [[_ x] n] (split-at n x))
[[] (range 1 8)]
(iterate inc 1))
(map first)
rest
(take-while seq))
;;=> ((1) (2 3) (4 5 6) (7))
Yet another approach...
(defn growing-chunks [src]
(->> (range)
(reductions #(drop %2 %1) src)
(take-while seq)
(map-indexed take)
rest))
(growing-chunks [:a :b :c :d :e :f :g :h :i])
;; => ((:a) (:b :c) (:d :e :f) (:g :h :i))

Why is this lazy-sequence not printing?

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

How to get tails of sequence clojure

I have sequence in clojure of theem
(1 2 3 4)
how can I get all the tails of sequence like
((1 2 3 4) (2 3 4) (3 4) (4) ())
Another way to get all tails is by using the reductions function.
user=> (def x '(1 2 3 4))
#'user/x
user=> (reductions (fn [s _] (rest s)) x x)
((1 2 3 4) (2 3 4) (3 4) (4) ())
user=>
If you want to do this with higher-level functions, I think iterate would work well here:
(defn tails [xs]
(concat (take-while seq (iterate rest xs)) '(()))
However, I think in this case it would be cleaner to just write it with lazy-seq:
(defn tails [xs]
(if-not (seq xs) '(())
(cons xs (lazy-seq (tails (rest xs))))))
Here is one way.
user=> (def x [1 2 3 4])
#'user/x
user=> (map #(drop % x) (range (inc (count x))))
((1 2 3 4) (2 3 4) (3 4) (4) ())
One way you can do that is by
(defn tails [coll]
(take (inc (count coll)) (iterate rest coll)))
(defn tails
[s]
(cons s (if-some [r (next s)]
(lazy-seq (tails r))
'(()))))
Yippee! Another one:
(defn tails [coll]
(if-let [s (seq coll)]
(cons coll (lazy-seq (tails (rest coll))))
'(())))
This is really just what reductions does under the hood. The best answer, by the way, is ez121sl's.