And predicate filtering clojure - clojure

I have function that takes any amount of predicates and filters the seq for each one of them like this:
(defn andp [& fns]
(fn [& args]
(every? #(apply % args) fns)))
(defn pred-and
([] "what to return")
([x] x)
([x y] (andp x y))
([x y & more]
(reduce pred-and (pred-and x y) more)
)
)
This works as expected for 1 2 or more params like this:
(filter (pred-and pos? odd?) [1 2 -4 0 6 7 -3]) => [1 7] // For one parameter
(filter (pred-and number? integer? pos? even?) [1 0 -2
:a 7 "a" 2]) => [2] // For two parameters
The problem is when I pass no parameters, it should return the original sequence how to do that?
(filter (pred-and) [1 0 -2]) => [1 0 -2]

as per the docs filter
returns a lazy sequence of the items in coll for which (pred item) returns true.
To get the original sequence, (pred item) must return true for every item.
(fn [x] true) should do the trick.

Related

Comparing each neighboring pairs in clojure vector

I'm learning Clojure. I found some exercises which require finding indexes for values in an array which are, for example, lower than next value. In Java I'd write
for (int i = 1; ...)
if (a[i-1] < a[i]) {result.add(i-1)}
in Clojure I found keep-indexed useful:
(defn with-keep-indexed [v]
(keep-indexed #(if (> %2 (get v %1)) %1) (rest v)))
It seems to works ok, but
is there a better way to do so?
This approach should work well for "find all values" or "find first value" (wrapped in first). But what if I need "find last". Then I have to either (with-keep-indexed (reverse v)) or (last (with-keep-indexed v)). Is there better way?
Edit: Example: for [1 1 2 2 1 2]
(with-keep-indexed [1 1 2 2 1 2])
;;=> (1 4)
Use partition to transform the vector to a sequence of consecutive pairs. Then use keep-indexed to add an index and filter them:
(defn indices< [xs]
(keep-indexed (fn [i ys]
(when (apply < ys) i))
(partition 2 1 xs)))
(indices< [1 1 2 2 1 2]) ;; => (1 4)
To find just the last such index, use last on this result. While it is possible to use reverse on the input, it does not offer any performance benefit for this problem.
The logic of forming pairs of numbers and comparing each number to the next number in the sequence can be factored out in a transducer that does not care about whether you want your result in the form of a vector with all indices or just the last index. Forming pairs can be done using partition as already suggested in the other answers, but I did not find a transducer implementation of that function, which would greatly facilitate. Here is a workaround that uses a mapping transducer along with some mutable state.
(defn indexed-pairs []
(let [s (atom [-2 nil nil])]
(comp (map #(swap! s (fn [[i a b]] [(inc i) b %])))
(remove (comp neg? first)))))
(defn indices-of-pairs-such-that [f]
(comp (indexed-pairs)
(filter (fn [[i a b]] (f a b)))
(map first)))
In this code, the function indices-of-pairs-such-that will return a transducer that we can use in various ways, for instance with into to produce a vector of indices:
(into [] (indices-of-pairs-such-that <) [1 1 2 2 1 2])
;; => [1 4]
Or, as was asked in the question, we can use tranduce along with a reducing function that always picks the second argument if we only want the last index:
(transduce (indices-of-pairs-such-that <) (completing (fn [a b] b)) nil [1 1 2 2 1 2])
;; => 4
This is the power of transducers: they decouple sequence algorithms from the results of those algorithms. The function indices-of-pairs-such-that encodes the sequence algorithm but does not have to know whether we want all the indices or just the last index.
The general problem can be solved with ...
(defn indexes-of-pairs [p coll]
(let [check-list (map (fn [i x rx] (when (p x rx) i)) (range) coll (rest coll))]
(filter identity check-list)))
... which returns the indexes of adjacent pairs of a sequence coll that are related by predicate p. For example,
(indexes-of-pairs < [1 1 2 2 1 2])
=> (1 4)
For your example, you can define
(def with-keep-indexed (partial indexes-of-pairs <))
Then
(with-keep-indexed [1 1 2 2 1 2])
=> (1 4)
There are many ways to solve a problem. Here are two alternatives, including a unit test using my favorite template project. The first one uses a loop over the first (N-1) indexes in an imperative style not so different than what you'd write in Java:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(defn step-up-index-loopy
[xs] ; a sequence of "x" values
(let-spy
[xs (vec xs) ; coerce to vector in case we get a list (faster)
accum (atom []) ; an accumulator
N (count xs)]
(dotimes [i (dec N)] ; loop starting at i=0
(let-spy [j (inc i)
ival (get xs i)
jval (get xs j)]
(when (< ival jval)
(swap! accum conj i))))
#accum))
When run, it produces this output:
calling step-up-index-loopy
xs => [1 1 2 2 1 2]
accum => #object[clojure.lang.Atom 0x4e4dcf7c {:status :ready, :val []}]
N => 6
j => 1
ival => 1
jval => 1
j => 2
ival => 1
jval => 2
j => 3
ival => 2
jval => 2
j => 4
ival => 2
jval => 1
j => 5
ival => 1
jval => 2
The second one uses a more "functional" style that avoids direct indexing. Sometimes this makes things simpler, but sometimes it can appear more complicated. You be the judge:
(defn step-up-index
[xs] ; a sequence of "x" values
(let-spy-pretty
[pairs (partition 2 1 xs)
pairs-indexed (indexed pairs) ; append index # [0 1 2 ...] to beginning of each pair
reducer-fn (fn [accum pair-indexed]
; destructure `pair-indexed`
(let-spy [[idx [ival jval]] pair-indexed]
(if (< ival jval)
(conj accum idx)
accum)))
result (reduce reducer-fn
[] ; initial state for `accum`
pairs-indexed)]
result))
The function indexed is from the Tupelo Clojure library.
When you run the code you'll see:
calling step-up-index
pairs =>
((1 1) (1 2) (2 2) (2 1) (1 2))
pairs-indexed =>
([0 (1 1)] [1 (1 2)] [2 (2 2)] [3 (2 1)] [4 (1 2)])
reducer-fn =>
#object[tst.demo.core$step_up_index$reducer_fn__21389 0x108aaf1f "tst.demo.core$step_up_index$reducer_fn__21389#108aaf1f"]
[idx [ival jval]] => [0 [1 1]]
[idx [ival jval]] => [1 [1 2]]
[idx [ival jval]] => [2 [2 2]]
[idx [ival jval]] => [3 [2 1]]
[idx [ival jval]] => [4 [1 2]]
result =>
[1 4]
Both of them work:
(dotest
(newline)
(println "calling step-up-index-loopy")
(is= [1 4]
(step-up-index-loopy [1 1 2 2 1 2]))
(newline)
(println "calling step-up-index")
(is= [1 4]
(step-up-index [1 1 2 2 1 2])))
With results:
-----------------------------------
Clojure 1.10.3 Java 15.0.2
-----------------------------------
Testing tst.demo.core
Ran 2 tests containing 2 assertions.
0 failures, 0 errors.
The form let-spy is from the Tupelo Clojure library, and makes writing & debugging things easier. See the docs for more info. When satisfied everything is working, replace with
let-spy => let
Also be sure to study the list of documentation sources included in the template project, especially the Clojure CheatSheet.
Another solution using keep-indexed is pretty short:
(defn step-up-index
[xs]
(let [pairs (partition 2 1 xs)
result (vec
(keep-indexed
(fn [idx pair]
(let [[ival jval] pair]
(when (< ival jval)
idx)))
pairs))]
result))
(dotest
(is= [1 4] (step-up-index [1 1 2 2 1 2])))

Function composition with variable function arguments

I am currently struggling with an assignment to create an anonymous function, in order to fulfil the following test cases:
Test case 1:
(= [3 2 1] ((__ rest reverse) [1 2 3 4]))
Test case 2:
(= 5 ((__ (partial + 3) second) [1 2 3 4]))
Test case 3:
(= true ((__ zero? #(mod % 8) +) 3 5 7 9))
Test case 4:
(= "HELLO" ((__ #(.toUpperCase %) #(apply str %) take) 5 "hello world"))
I came up with the solution:
(fn [& fs]
(fn [& items] (reduce #(%2 %1)
(flatten items)
(reverse fs))))
My idea was to create a list of the functions bound to the outer function, and then to apply a reducer on this function list, beginning with array "items".
As this works fine for chaining single arity functions in test cases 1 and 2, I have no idea how to modify the inner Lambda-function, in order to deal with multi-arity functions:
(apply + ___ ) ;; first function argument of test case 3
(take 5 ___ ) ;; first function argument of test case 4
Is there still a way to get around this problem?
Many thanks!
Source:
4Clojure - Problem 58
Addendum: I came across a "funky" solution using:
(fn [& fs] (reduce (fn [f g] #(f (apply g %&))) fs))
I don't fully understand this approach, to be honest...
Addendum 2: There was a similar discussion on this topic 7 years ago:
Clojure: Implementing the comp function
There I found the following solution:
(fn [& xs]
(fn [& ys]
(reduce #(%2 %1)
(apply (last xs) ys) (rest (reverse xs)))))
However, I still do not understand how we are able to kick off the reducer on the expression (apply (last xs) ys) , which represents the left-most function in the function chain.
In test case 1, that would translate to (apply rest [1 2 3 4]), which is wrong.
This is very similar to how comp is implemented in clojure.core.
(defn my-comp
([f] f)
([f g]
(fn
([] (f (g)))
([x] (f (g x)))
([x y] (f (g x y)))
([x y & args] (f (apply g x y args)))))
([f g & fs]
(reduce my-comp (list* f g fs))))
The key to understanding higher order function like comp is to think about what needs to happen when we compose functions.
What is the simplest case ? (comp f) Comp only receiving a single function, so we just return that function, there is no composition yet. How about second most simple case: Comp receiving two functions, like (comp f g), now we need to return another function which when called, does the composition, like (f (g)). But this returned function needs to support zero or more arguments, so we make it variadic. Why does it need to support zero or more arguments ? Because of function g, the inner most function can have zero or more arguments.
For example: what does (comp dec inc) return ?
It returns this fn:
(fn
([] (dec (inc)))
([x] (dec (inc x)))
([x y] (dec (inc x y)))
([x y & args] (dec (apply inc x y args)))))
It assumes that inc (the inner most function which gets executed first) could receive zero or more args. But in reality inc only supports one argument, so you would get the arity exception if you called this function with more than one argument like this ((comp dec inc) 1 2), but calling it with single argument would work, because the inner most function inc has a single arity, ((comp dec inc) 10). I hope I am clear here, why this returned function needs to be variadic.
Now for the next step, what if we compose three or more functions ? This is simple now, because the bread and butter was already implemented with two argument function that my-comp supports. So we just call this 2 argument function while we reduce through a list of supplied functions. Each step returns a new function which wraps the input function.
The first two test cases have the rest params: [[1 2 3 4]], not [1 2 3 4].
So it's not (apply rest [1 2 3 4]) but (apply rest [[1 2 3 4]]) or (rest [1 2 3 4]).
To drill it home:
(rest-ex [& rst]
rst
)
(rst 1 2 3) ;;=> [1 2 3]
(rst [1 2] 3) ;;=> [[1 2] 3]
(rst [1 2 3]) ;;=> [[1 2 3]]
Using apply:
; rest example one
(apply + [1 2 3]) ;;=> 6
; rest example two
(apply conj [[1 2] 3]) ;;=> [1 2 3]
; rest example three
(apply reverse [[1 2 3]]) ;;=> (3 2 1)
For both your funky solution and comp itself, it's like taking a car (the first function), beefing it up with a turbo, installing speakers (the following function). The car, w/ the turbo and amazing sound system, is available for the next group of friends to use (the apply turns it from a one-seat stock car to having as many "seats" as you want). In your case, the reducer function uses apply w/ a rest parameter, so it's like offering the option for more doors w/ each function added (but it chooses one door anyway).
The first two test cases are simple, and reduce isn't needed but can be used.
;; [[1 2 3 4]]
;; [rest reverse]
((fn [& fs] (reduce (fn [f g] #(f (apply g %&))) fs)) rest reverse) ;; is functionally equivalent to
((fn [& fs] #((first fs) (apply (second fs) %&))) rest reverse)
#(rest (apply reverse %&))
;; So
(((fn [& fs] (reduce (fn [f g] #(f (apply g %&))) fs)) rest reverse) [1 2 3 4]) ;; (3 2 1)
(((fn [& fs] #((first fs) (apply (second fs) %&))) rest reverse) [1 2 3 4]) ;; (3 2)
(#(rest (apply reverse %&)) [1 2 3 4]) ;;=> (3 2 1)
The third test case, on the second round of reduce, after it's started, looks like:
;; [3 5 7 9]
;; [zero? #(mod % 8) +]
;; ^ ^ The reducer function runs against these two f's
;; Which turns the original:
(fn [& fs] (reduce (fn [f g] #(f (apply g %&))) fs))
;; into an equivalent:
(reduce #(zero? (apply (fn [v] (mod v 8)) [g])) [+])
;; which ultimately results in (wow!):
((fn [& args] (zero? (apply (fn [v] (mod v 8)) [(apply + args)]))) 3 5 7 9)
Pay careful attention to the %& in the reducer function. that's why I wrapped (apply + args) in a vector.
While going through this, I realized what I intuited from my use of reduce is a tiny bit more involved than I realized--esp. w/ function composition, rest params, and apply at play.
It's not that simple, but it's understandable.

How do I create a function that inserts an element between each pair of elements in a vector

I want to write a function that inserts elements between existing elements in a vector. The inserted elements are a function of the elements that precede and succeed it, with the first and last elements remaining unaffected.
E.g. I want inserted elements to be the mean of the elements that precede and succeed it:
Input:
[1 10 15]
Output:
[1 5.5 10 12.5 15]
What is the best way to do this in Clojure?
Here's another way:
(defn insert-mean-between [xs]
(let [f (fn [x y]
[(* (+ x y) 0.5) y])]
(->> xs
(partition 2 1)
(mapcat (partial apply f))
(cons (first xs))
vec)))
(insert-mean-between [1 10 15])
;;=> [1 5.5 10 12.5 15]
The main trick is that f is returning the answer and the RHS input. This way later on they will all compose together without repeats. The only problem you will have is that the first element is missing. So we just cons it onto the front. From the outset we had to know that cons would be a convenient operation when we chose to be returning the RHS rather than the LHS.
As calculating the mean was just an example, an improved solution would be for the inserting to be independent of the mean/whatever function:
(defn calc-mean [x y] (* (+ x y) 0.5)
(insert-between calc-mean [1 10 15])
Then a more general inserting function might be:
(defn insert-between [g xs]
(->> xs
(partition 2 1)
(mapcat (fn [[x y]] [(g x y) y]))
(cons (first xs))))
and the list of variants won't be complete without the recursive lazy sequence generation:
(defn with-avg [[x1 & [x2 :as tail] :as items]]
(when (seq items)
(if (seq tail)
(lazy-cat [x1 (/ (+ x1 x2) 2)] (with-avg tail))
[x1])))
user> (with-avg [1 2 3 4 5])
;;=> (1 3/2 2 5/2 3 7/2 4 9/2 5)
user> (with-avg [1])
;;=> [1]
user> (with-avg [])
;;=> nil
user> (with-avg [1 2])
;;=> (1 3/2 2)
user> (with-avg [1 2 3])
;;=>(1 3/2 2 5/2 3)
One way I could solve it is pattern matching Vector as f s t, I'm assuming it has 3 elements
Then create variable to assign first median first + second / 2 and second median second + third /2.
At the end return a new Vector with a combination you want.
Example, (I'm using lein REPL)
user=> (defn insert_medians[vect]
#_=> (let [[f s t] vect
#_=> m1 (float (/ (+ f s) 2))
#_=> m2 (float (/ (+ s t) 2))]
#_=> [f m1 s m2 t]))
#'user/insert_medians
user=> (insert_medians [1 10 15])
[1 5.5 10 12.5 15]
If a vector is larger than 3 elems, you need to find all the medians first and then insert into the original vector using interleave fn.
(defn insert-between
"Inserts elements between existing elements in a vector v. The inserted
elements are a result of applying the function f to the elements that precede
and succeed it, with the first and last elements of v remaining unaffected."
[f [x & xs :as v]]
(->> (partition 2 1 v)
(mapcat (fn [[a b]] [(f a b) b]))
(cons x)
(into [])))
(defn mean [& numbers]
(float (/ (apply + numbers) (count numbers))))
(insert-between mean [1 10 15]) ; => [1 5.5 10 10 12.5 15]
(insert-between + [1 10 15 20 25]) ; => [1 11 10 25 15 35 20 45 25]
(insert-between mean []) ; => [nil] :(

Sequence of all but the last elements of a collection for which a predicate is true

I’m having trouble writing an elegant drop-last-by or butlast-by function.
(drop-last-by odd? [2 1 9 4 7 7 3]) ; => (2 1 9 4)
(drop-last-by odd? [2 4]) ; => (2 4)
(drop-last-by odd? [9]) ; => ()
What I have so far works but seems a little clumsy and I wonder if it can be done in just two or three lines.
(defn drop-last-by [pred coll]
(let [p (partition-by pred coll)]
(apply concat (if (and (seq p) (pred (first (last p))))
(butlast p)
p))))
Since drop-while already does basically what you need, and since your current solution is already not lazy, I'd write drop-last-by like this:
(defn drop-last-by [pred coll]
(reverse (drop-while pred (reverse coll))))
The version below is lazy to the degree permitted by the problem specification:
any elements that do not satisfy the predicate are immediately passed through without reading any additional elements from the source;
any elements that do satisfy the predicate are passed through as soon as an element that does not satisfy the predicate is read in from the source;
any elements that satisfy the predicate and are not followed by further elements that do not satisfy the predicate are dropped.
Additionally, it can be used as a (stateful) transducer; indeed the lazy seq version is implemented in terms of the transducer and clojure.core/sequence.
(defn drop-last-by
([pred]
(fn [rf]
(let [xs (volatile! [])]
(fn
([] (rf))
([result] (rf result))
([result input]
(if-not (pred input)
(do
(reduce rf result #xs)
(vreset! xs [])
(rf result input))
(do
(vswap! xs conj input)
result)))))))
([pred coll]
(sequence (drop-last-by pred) coll)))
At the REPL:
(drop-last-by odd? [2 1 9 4 7 7 3])
;= (2 1 9 4)
(drop-last-by odd? [2 4])
;= (2 4)
(drop-last-by odd? [9])
;= ()
Composed with other transducers:
(into []
(comp (drop-while even?)
(drop-last-by odd?)
(map #(str "foo " %)))
[0 1 2 3 4 5])
;= ["foo 1" "foo 2" "foo 3" "foo 4"]

Perform multiple reductions in a single pass in Clojure

In Clojure I want to find the result of multiple reductions while only consuming the sequence once. In Java I would do something like the following:
double min = Double.MIN_VALUE;
double max = Double.MAX_VALUE;
for (Item item : items) {
double price = item.getPrice();
if (price > min) {
min = price;
}
if (price < max) {
max = price;
}
}
In Clojure I could do much the same thing by using loop and recur, but it's not very composable - I'd like to do something that lets you add in other aggregation functions as needed.
I've written the following function to do this:
(defn reduce-multi
"Given a sequence of fns and a coll, returns a vector of the result of each fn
when reduced over the coll."
[fns coll]
(let [n (count fns)
r (rest coll)
initial-v (transient (into [] (repeat n (first coll))))
fns (into [] fns)
reduction-fn
(fn [v x]
(loop [v-current v, i 0]
(let [y (nth v-current i)
f (nth fns i)
v-new (assoc! v-current i (f y x))]
(if (= i (- n 1))
v-new
(recur v-new (inc i))))))]
(persistent! (reduce reduction-fn initial-v r))))
This can be used in the following way:
(reduce-multi [max min] [4 3 6 7 0 1 8 2 5 9])
=> [9 0]
I appreciate that it's not implemented in the most idiomatic way, but the main problem is that it's about 10x as slow as doing the reductions one at at time. This might be useful for lots performing lots of reductions where the seq is doing heavy IO, but surely this could be better.
Is there something in an existing Clojure library that would do what I want? If not, where am I going wrong in my function?
that's what i would do: simply delegate this task to a core reduce function, like this:
(defn multi-reduce
([fs accs xs] (reduce (fn [accs x] (doall (map #(%1 %2 x) fs accs)))
accs xs))
([fs xs] (when (seq xs)
(multi-reduce fs (repeat (count fs) (first xs))
(rest xs)))))
in repl:
user> (multi-reduce [+ * min max] (range 1 10))
(45 362880 1 9)
user> (multi-reduce [+ * min max] [10])
(10 10 10 10)
user> (multi-reduce [+ * min max] [])
nil
user> (multi-reduce [+ * min max] [1 1 1000 0] [])
[1 1 1000 0]
user> (multi-reduce [+ * min max] [1 1 1000 0] [1])
(2 1 1 1)
user> (multi-reduce [+ * min max] [1 1 1000 0] (range 1 10))
(46 362880 1 9)
user> (multi-reduce [max min] (range 1000000))
(999999 0)
The code for reduce is fast for reducible collections. So it's worth trying to base multi-reduce on core reduce. To do so, we have to be able to construct reducing functions of the right shape. An ancillary function to do so is ...
(defn juxt-reducer [f g]
(fn [[fa ga] x] [(f fa x) (g ga x)]))
Now we can define the function you want, which combines juxt with reduce as ...
(defn juxt-reduce
([[f g] coll]
(if-let [[x & xs] (seq coll)]
(juxt-reduce (list f g) [x x] xs)
[(f) (g)]))
([[f g] init coll]
(reduce (juxt-reducer f g) init coll)))
For example,
(juxt-reduce [max min] [4 3 6 7 0 1 8 2 5 9]) ;=> [9 0]
The above follows the shape of core reduce. It can clearly be extended to cope with more than two functions. And I'd expect it to be faster than yours for reducible collections.
Here is how I would do it:
(ns clj.core
(:require [clojure.string :as str] )
(:use tupelo.core))
(def data (flatten [ (range 5 10) (range 5) ] ))
(spyx data)
(def result (reduce (fn [cum-result curr-val] ; reducing (accumulator) fn
(it-> cum-result
(update it :min-val min curr-val)
(update it :max-val max curr-val)))
{ :min-val (first data) :max-val (first data) } ; inital value
data)) ; seq to reduce
(spyx result)
(defn -main [] )
;=> data => (5 6 7 8 9 0 1 2 3 4)
;=> result => {:min-val 0, :max-val 9}
So the reducing function (fn ...) carries along a map like {:min-val xxx :max-val yyy} through each element of the sequence, updating the min & max values as required at each step.
While this does make only one pass through the data, it is doing a lot of extra work calling update twice per element. Unless your sequence is very unusual, it is probably more efficient to make two (very efficient) passes through the data like:
(def min-val (apply min data))
(def max-val (apply max data))
(spyx min-val)
(spyx max-val)
;=> min-val => 0
;=> max-val => 9