Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
421 PurelyFunctional.tv Newsletter

Element promotion

Sometimes you have a list and you want to "promote" one element toward the front of the list. Essentially, you need to swap the element with its immediate predecessor (if it exists). Write a function promote that takes a predicate and a list. If the predicate is true, the element should be promoted.

Examples

(promote even? [1 3 5 6]) ;=> (1 3 6 5)
(promote even? []) ;=> ()
(promote even? [2 1]) ;=> (2 1)
(promote even? [0 2 4 6]) ;=> (0 2 4 6)
(promote even? [0 1 2 3 4 5 6]) ;=> (0 2 1 4 3 6 5)
(promote even? [1 2 2 2 2]) ;=> (2 2 2 2 1)

Thanks to Enzzo Cavallo for the challenge idea!

Please submit your solutions as comments on this gist.

To subscribe: https://purelyfunctional.tv/newsletter/

@miner
Copy link

miner commented Apr 15, 2021

You have to be extra careful if you allow nils in your input collection.
(promote nil? [true nil false true nil nil])
;=> [nil true false nil nil true]

@KingCode
Copy link

KingCode commented Jun 12, 2021

(defn promote [pred xs]
  (->>
   (loop [[hd nxt & more :as all] xs acc []]
     (cond 
       (empty? all)
       acc 
       (= 1 (count all))
       (conj acc hd) 
       (or (pred hd) (not (pred nxt)))
       (recur (cons nxt more) (conj acc hd))
       :else 
       (recur (cons hd more) (conj acc nxt))))
   (apply list)))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment