How to move first list item to the end? - clojure

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)

Related

Find elements in list and also keep adjacent element

i have a list like '(1 2 3 1 4 1 1 6 8 9 0 1) (not actually of numbers, just as an example)
I want to keep all "1" and the element next to the "1".
So the result i would want is (1 2 1 4 1 1 6 1).
Coming from an imperative point of view i would iterate over the list with a for loop, find the "1" at a certain index i and then also keep the element at index i+1.
What would a functional, Clojure idiomatic way of solving this problem be?
Using reduce you can move along the original list building a new list as you go. The reducing function f is passed the new list up until now and the next element from the old list. If the list up until now ends with a 1, or the next element is a 1, add the element to the new list. Otherwise keep the new list as is and move along.
user> (def xs [1 2 3 1 4 1 1 6 8 9 0 1])
#'user/xs
user> (defn f [x y] (if (or (= 1 y) (= 1 (peek x))) (conj x y) x))
#'user/f
user> (reduce f [] xs)
[1 2 1 4 1 1 6 1]
When you can't think of anything clever with sequence combinators, write the recursion by hand. It's not exactly elegant, but it's lazy:
(defn keep-pairs [pred coll]
(lazy-seq
(if (empty? coll)
[]
(let [x (first coll)
xs (next coll)]
(if (pred x)
(cons x (when xs
(let [y (first xs)]
(concat (when-not (pred y) [y])
(keep-pairs pred xs)))))
(when xs
(keep-pairs pred xs)))))))
user> (keep-pairs #{1} [1 2 3 1 4 1 1 6 8 9 0 1])
(1 2 1 4 1 1 6 1)
user> (take 10 (keep-pairs #{1} (cycle [1 2 3])))
(1 2 1 2 1 2 1 2 1 2)
I think I'd prefer reduce for something like this, but here's another 'functional' way of looking at it:
You have a sequence of values that should produce a potentially smaller sequence of values based on some predicate (i.e. filtering) and that predicate needs look-ahead/-behind behavior.
A less common use for map is mapping over multiple sequences at once e.g. (map f coll1 coll2 coll3). If you pass in an "offset" version of the same collection it can be used for the look-ahead/-behind logic.
(defn my-pairs [coll]
(mapcat
(fn [prev curr]
(when (or (= 1 prev) (= 1 curr))
[curr]))
(cons ::none coll) ;; these values are used for look-behind
coll))
This is (ab)using mapcat behavior to combine the mapping/filtering into one step, but it could also be phrased with map + filter.
here's one more solution with clojure's seq processors composition:
(defn process [pred data]
(->> data
(partition-by pred)
(partition-all 2 1)
(filter (comp pred ffirst))
(mapcat #(concat (first %) (take 1 (second %))))))
user> (process #{1} [1 2 1 1 3 4 1 5 1])
;;=> (1 2 1 1 3 1 5 1)
user> (process #{1} [0 1 2 1 1 1 3 4 1 5 1 6])
;;=> (1 2 1 1 1 3 1 5 1 6)
Another idea that does not work since it misses a last one:
(def v [1 2 3 1 4 1 1 6 8 9 0 1])
(mapcat (fn [a b] (when (= a 1) [a b])) v (rest v))
;; => (1 2 1 4 1 1 1 6 1)
So use two arity version of mapcat over the vector and the vector shifted one to the right.
You could check that last 1 explicitly and add, then you get a less elegant working version:
(concat
(mapcat (fn [a b] (when (= a 1) [a b])) v (rest v))
(when (= (peek v) 1) [1]))
;; => (1 2 1 4 1 1 1 6 1)
When you need to loop over data and retain state, I think a plain-old loop/recur is the most straightforward technique:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(defn keep-pairs
[data]
(loop [result []
prev nil
remaining data]
(if (empty? remaining)
result
(let [curr (first remaining)
keep-curr (or (= 1 curr)
(= 1 prev))
result-next (if keep-curr
(conj result curr)
result)
prev-next curr
remaining-next (rest remaining)]
(recur result-next prev-next remaining-next)))))
(dotest
(let [data [1 2 3 1 4 1 1 6 8 9 0 1]]
(is= [1 2 1 4 1 1 6 1]
(keep-pairs data))))
(defn windowed-pred [n pred]
(let [window (atom [])]
(fn [rf]
(fn ([] (rf))
([acc] (rf acc))
([acc v]
(let [keep? (or (pred v) (some pred #window))]
(swap! window #(vec (take-last n (conj %1 %2))) v)
(if keep?
(rf acc v)
acc)))))))
(let [c [1 2 3 1 4 1 1 6 8 9 0 1]
pred #(= % 1)]
(eduction (windowed-pred 1 pred) c))
(defn last-or-first? [obj pair] (or (= obj (last pair)) (= obj (first pair))))
; to test, whether previous element or element is object
(defn back-shift [l] (cons nil (butlast l))) ;; back-shifts a list
(defn keep-with-follower
[obj l]
(map #'last ; take only the element itself without its previous element
(filter #(last-or-first? obj %) ; is element or previous element the object?
(map #'list (back-shift l) l)))) ; group previous element and element in list
(def l '(1 2 3 1 4 1 1 6 8 9 0 1))
(keep-with-follower 1 l)
;; => (1 2 1 4 1 1 6 1)
A functional solution using only cons first last butlast list map filter = and defn and def.

Mysterious Clojure function

I would like to write a clojure function that has the following behaviour :
(take 4 (floyd))
=> '((1) (2 3) (4 5 6) (7 8 9 10))
(take 3 (floyd))
=> '((1) (2 3) (4 5 6))
(take 1 (floyd))
=> '((1)))
I tried using partition and partition-all to validate these tests however i couldn't get the right solution. If you have any idea of how to do it, i would really appreciate a little help. I started using clojure a few weeks ago and still have some issues.
Thanks
Here's another option:
(defn floyd []
(map (fn [lo n] (range lo (+ lo n 1)))
(reductions + 1 (iterate inc 1))
(range)))
(take 5 (floyd))
;=> ((1) (2 3) (4 5 6) (7 8 9 10) (11 12 13 14 15))
This was arrived at based on the observation that you want a series of increasing ranges (the (range) argument to map is used to produce a sequence of increasingly longer ranges), each one starting from almost the triangular number sequence:
(take 5 (reductions + 0 (iterate inc 1)))
;=> (0 1 3 6 10)
If we start that sequence from 1 instead, we get the starting numbers in your desired sequence:
(take 5 (reductions + 1 (iterate inc 1)))
;=> (1 2 4 7 11)
If the + 1 inside the mapped function bothers you, you could do this instead:
(defn floyd []
(map (fn [lo n] (range lo (+ lo n)))
(reductions + 1 (iterate inc 1))
(iterate inc 1)))
it is not possible to solve it with partition / partition-all, since they split your sequence into predefined size chunks.
What you can do, is to employ recursive lazy function for that:
user> (defn floyd []
(letfn [(f [n rng]
(cons (take n rng)
(lazy-seq (f (inc n) (drop n rng)))))]
(f 1 (iterate inc 1))))
#'user/floyd
user> (take 1 (floyd))
;;=> ((1))
user> (take 2 (floyd))
;;=> ((1) (2 3))
user> (take 3 (floyd))
;;=> ((1) (2 3) (4 5 6))
user> (take 4 (floyd))
;;=> ((1) (2 3) (4 5 6) (7 8 9 10))
another variant can use similar approach, but only track chunk-start/chunk-size:
user> (defn floyd []
(letfn [(f [n start]
(cons (range start (+ start n))
(lazy-seq (f (inc n) (+ start n)))))]
(f 1 1)))
another approach is to use clojure's collection operating functions:
user> (defn floyd-2 []
(->> [1 1]
(iterate (fn [[start n]]
[(+ n start) (inc n)]))
(map (fn [[start n]] (range start (+ start n))))))
#'user/floyd-2
user> (take 4 (floyd-2))
;;=> ((1) (2 3) (4 5 6) (7 8 9 10))
user> (take 5 (floyd-2))
;;=> ((1) (2 3) (4 5 6) (7 8 9 10) (11 12 13 14 15))
user> (take 1 (floyd-2))
;;=> ((1))
How about this:
(defn floyd []
(map (fn[n]
(let [start (/ (* n (inc n)) 2)]
(range (inc start) (+ start n 2))))
(iterate inc 0)))
(take 4 (floyd))

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

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