Function related to partition that includes all elements? - clojure

This behavior of Clojure's partition function is not what I need:
user=> (partition 3 (range 3))
((0 1 2))
user=> (partition 3 (range 4))
((0 1 2))
user=> (partition 3 (range 5))
((0 1 2))
user=> (partition 3 (range 6))
((0 1 2) (3 4 5))
I need the 'leftover' portions of the collection to be included, e.g.:
user=> (partition* 3 (range 4))
((0 1 2) (3))
user=> (partition* 3 (range 5))
((0 1 2) (3 4))
Is there a standard library function that does what I want?

You're looking for partition-all. Just replace it in your example:
user> (partition-all 3 (range 4))
((0 1 2) (3))
user> (partition-all 3 (range 5))
((0 1 2) (3 4))

There is a pad argument in the 4-arity version of partition:
user=> (partition 3 3 [] (range 4))
((0 1 2) (3))
user=> (partition 3 3 [] (range 5))
((0 1 2) (3 4))
The docstring:
user=> (doc partition)
-------------------------
clojure.core/partition
([n coll] [n step coll] [n step pad coll])
Returns a lazy sequence of lists of n items each, at offsets step
apart. If step is not supplied, defaults to n, i.e. the partitions
do not overlap. If a pad collection is supplied, use its elements as
necessary to complete last partition upto n items. In case there are
not enough padding elements, return a partition with less than n items.

Related

Drop function in clojure

Given the following function, I could not understand what map function is receiving as second parameter.
(def tails
(fn [seq]
(map drop
(range (inc (count seq)))
(repeat (inc (count seq)) seq))))
Given that seq is (list 1 2 3)
The line:
(range (inc (count seq)))
Will produce ((1 2 3) (1 2 3) (1 2 3))
And the line:
(range (inc (count seq)))
Will produce (0 1 2 3)
So, what is receiving the map function as second parameter?
The second parameter is seq repeated as many times as its length + 1, so you can drop 0 to length elements from it.
For '(1 2 3), you get
(map drop '(0 1 2 3) (repeat 4 '( 1 2 3)))
which (when realized) will become the equivalent of
(list (drop 0 '(1 2 3)) (drop 1 '(1 2 3)) (drop 2 '(1 2 3)) (drop 3 '(1 2 3)))
which evaluates to
((1 2 3) (2 3) (3) ())

How to move first list item to the end?

For given list:
(1 2 3 4)
I'd like to get as output:
(2 3 4 1)
Code I came up with looks like this:
(flatten (cons (rest l) (list (first l))))
However my feeling is, that I overcomplicated this. Any other ideas?
You don't need to flatten a cons, just use concat.
Here is an example:
(let [fruit ["apple" "orange" "grapes" "bananas"]]
(concat (rest fruit) [(first fruit)])
Developing #stonemetal's hint, we can quickly and lazily rotate a vector thus:
(defn rotate [v n]
(let [cv (count v), n (mod n cv)]
(concat (subvec v n cv) (subvec v 0 n))))
It works in either direction:
(map #(rotate (vec (range 5)) %) (range -2 8))
;((3 4 0 1 2)
; (4 0 1 2 3)
; (0 1 2 3 4)
; (1 2 3 4 0)
; (2 3 4 0 1)
; (3 4 0 1 2)
; ...
; (2 3 4 0 1))
So to rotate the first in a sequence to the end:
(rotate (vec (range 1 5)) 1)
You can also use destructuring (either on the function arguments or in a let binding).
(let [[h & tail] '(1 2 3 4)]
(concat tail (list h))) ;=> (1 2 3 4)

How to verify if a list is sorted?

How can I, in Clojure, verify is a list of numbers is sorted?
(def my-list (list 1 2 3 1 4 2 2 4))
sorted? only returns true if the collection implements the sorted interface. I was looking for a reduce operation that would iterate the list pairwise, such as (reduce < my-list).
I understand I could manually create pairs and compare these:
(letfn [(pair [l] (if (= (count l) 2) (list l) (cons (take 2 l) (pair (rest l)))))]
(every? #(apply < %) (pair my-list)))
But that seems unnecessarily complex. It really seems to me as if I'm missing a basic function.
The simplest solution:
(apply <= mylist)
>= also works for reverse sorting
I would do a single pass over overlapping pairs of numbers and check they are <= (as you mention) because it is O(n), though you don't need to manually make pairs.
user> (partition-all 2 1 [1 2 3 4 5 6])
((1 2) (2 3) (3 4) (4 5) (5 6) (6))
user> (every? #(apply <= %) (partition-all 2 1 [1 2 3 4 6 5]))
false
user> (every? #(apply <= %) (partition-all 2 1 [1 2 3 4 5 6]))
true
You could sort the list and compare it to the original:
(= my-list (sort my-list))
Example:
> (def my-list (list 1 2 3 1 4 2 2 4))
#'sandbox3825/my-list
> (= my-list (sort my-list))
false
> (def my-list (list 1 2 3 4))
#'sandbox3825/my-list
> (= my-list (sort my-list))
true

How does this function which reverses the interleave process into x number of subsequences

I completed exercise 43 on 4clojure the other day and checked some of the other solutions. One in particular has confused me.
The challenge asks you to write a function which satisfies all of these:
(= (__ [1 2 3 4 5 6] 2) '((1 3 5) (2 4 6)))
(= (__ (range 9) 3) '((0 3 6) (1 4 7) (2 5 8)))
(= (__ (range 10) 5) '((0 5) (1 6) (2 7) (3 8) (4 9)))
My solution was this:
(fn [l n]
(map #(map second %) (vals (group-by #(mod (first %) n)
(map vector (iterate inc 0) l)))))
User himself had this solution:
#(apply map list (partition %2 %1))
and I couldn't work out how it worked.
Let's work through the first problem:
(= (__ [1 2 3 4 5 6] 2) '((1 3 5) (2 4 6)))
well the (#(partition %2 %1) [1 2 3 4 5 6] 2) would give us ((1 2) (3 4) (5 6)) now how does apply map list on that produce (1 3 5) (2 4 6)
apply is using the ((1 2) (3 4) (5 6)) as a variable length list of additional arguments. Then iteration of the map is applying the list function to all three of these additional lists.
As a result it expands as follows:
(apply map list '((1 2) (3 4) (5 6)))
=> (map list '(1 2) '(3 4) '(5 6))
=> (list 1 3 5) and (list 2 4 6)

Sliding window over seq

In Clojure, what would be the nicest way to have a sliding window over a (finite, not too large) seq? Should I just use drop and take and keep track of the current index or is there a nicer way I'm missing?
I think that partition with step 1 does it:
user=> (partition 3 1 [3 1 4 1 5 9])
((3 1 4) (1 4 1) (4 1 5) (1 5 9))
If you want to operate on the windows, it can also be convenient to do this with map:
user=> (def a [3 1 4 1 5 9])
user=> (map (partial apply +) (partition 3 1 a))
(8 6 10 15)
user=> (map + a (next a) (nnext a))
(8 6 10 15)
I didn't know partition could do this so I implemented it this way
(defn sliding-window [seq length]
(loop [result ()
remaining seq]
(let [chunk (take length remaining)]
(if (< (count chunk) length)
(reverse result)
(recur (cons chunk result) (rest remaining))))))