Skip to content

Instantly share code, notes, and snippets.

@souenzzo
Last active Apr 6, 2021
Embed
What would you like to do?

Função promover/rebaixar (parte 1)

Dado uma coleção coll, por exemplo, [:a :b :c :d :e] e um predicado pred, por exemplo #{:c}, implementar uma função promover que recebe (promover #{:c} [:a :b :c :d :e]) e retorna a coleção com o elemento selecionado "uma posição a frente": [:a :c :b :d :e]

Implementar também a função rebaixar, com a mesma assinatura, porém resulta em [:a :b :d :c :e]

Os casos de borda (elementos repetidos, agrupamentos degenerados) não são importantes.

O unico caso de teste realmente necessário é o descrito no enumciado:

  • o pred só irá bater em um elemento
  • o elemento não estará em nenhuma das extremidades da lista

EXTRA

Fazer uma função promover+rebaixar genérica, onde o pred retorna um int? que indica quantas posições o elemento será promovido/rebaixado.

@mauricioszabo

This comment has been minimized.

Copy link

@mauricioszabo mauricioszabo commented Mar 8, 2021

Promover:

(defn promover [pred collection]
  (loop [acc (subvec collection 0 1)
         collection (subvec collection 1)]
    (let [last-old (peek acc)
          first-new (first collection)]
      (cond
        (empty? collection) acc
        (pred first-new) (recur
                           (-> acc pop (conj first-new last-old))
                           (subvec collection 1))
        :else (recur
                (conj acc first-new)
                (subvec collection 1))))))
@mauricioszabo

This comment has been minimized.

Copy link

@mauricioszabo mauricioszabo commented Mar 8, 2021

Rebaixar:

(defn rebaixar [pred collection]
  (loop [acc (subvec collection 0 1)
         collection (subvec collection 1)]
    (let [last-old (peek acc)
          first-new (first collection)
          not-last (-> collection count (> 1))
          match? (delay (pred last-old))]
      (cond
        (empty? collection) acc
        
        (and @match? not-last) (recur
                                 (-> acc pop (conj first-new 
                                                   last-old 
                                                   (second collection))) 
                                 (subvec collection 2))
          
        @match? (recur
                  (-> acc pop (conj first-new last-old))
                  (subvec collection 1))
        
        :else (recur
                (conj acc first-new)
                (subvec collection 1))))))
@yvern

This comment has been minimized.

Copy link

@yvern yvern commented Mar 8, 2021

(defn- demote'
  ([coll selected] (demote' coll selected 1))
  ([coll selected ranks]
   (let [[above bellow] (split-at ranks coll)]
     (concat above (conj bellow selected)))))

(defn- promote'
  ([coll selected] (promote' coll selected 1))
  ([coll selected ranks] (reverse (demote' (reverse coll) selected ranks))))

(defn- splitter [pred coll]
  (let [[before [selected & after]] (split-with (complement pred) coll)]
    [before selected after]))

(defn promote
  ([pred coll] (promote pred coll 1))
  ([pred coll ranks]
   (let [[before selected after]
         (splitter pred coll)]
     (concat (promote' before selected ranks) after))))

(defn demote
  ([pred coll] (demote pred coll 1))
  ([pred coll ranks]
   (let [[before selected after]
         (splitter pred coll)]
     (concat before (demote' after selected ranks)))))

(defn move [ranks pred coll]
  ((if (pos-int? ranks) promote demote) pred coll (Math/abs ranks)))

(= coll (move 0 pred coll))
@souenzzo

This comment has been minimized.

Copy link
Owner Author

@souenzzo souenzzo commented Mar 8, 2021

(defn promover
  [pred els]
  (let [els (vec els)]
    (sequence (comp (map-indexed (fn [idx el]
                                   (let [nx (get els (inc idx))]
                                     (cond
                                       (pred nx) [nx el]
                                       (pred el) []
                                       :else [el]))))
                    cat)
              els)))

(defn rebaixar
  [pred els]
  (let [els (vec els)]
    (sequence (comp (map-indexed (fn [idx el]
                                   (let [prev (get els (dec idx))]
                                     (cond
                                       (pred prev) [el prev]
                                       (pred el) []
                                       :else [el]))))
                    cat)
              els)))
@yvern

This comment has been minimized.

Copy link

@yvern yvern commented Mar 8, 2021

(defn rebaixar [steps pred coll]
  (let [[before [selected & after]] (split-with (complement pred) coll)
        [mid end] (split-at steps after)]
    (concat before mid (conj end selected))))

(defn promover [steps pred coll] (->> coll reverse (rebaixar steps pred) reverse))
@wilkerlucio

This comment has been minimized.

Copy link

@wilkerlucio wilkerlucio commented Apr 6, 2021

Uma versao que nao requer recriar as listas inteiras:

(defn swap-vec-indexes [v ia ib]
  (-> v
      (assoc ia (get v ib))
      (assoc ib (get v ia))))

(defn promover [pred coll]
  (let [item-idx (some (fn [[item n]]
                         (if (pred item)
                           n)) (map vector coll (range)))]
    (if (some-> item-idx pos?)
      (swap-vec-indexes coll (dec item-idx) item-idx)
      coll)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment