Skip to content

Instantly share code, notes, and snippets.

@domgetter
Last active January 8, 2016 11:30
Show Gist options
  • Save domgetter/3833a98997b58a2597f8 to your computer and use it in GitHub Desktop.
Save domgetter/3833a98997b58a2597f8 to your computer and use it in GitHub Desktop.
(defn partition-while
"partitions elements in order while the predicate function holds
the predicate function is given the current element
and the current partition. "
[f coll]
(loop [truck [] box [] [book & books] coll]
(if (empty? books) ; if there are no more books to pack
(conj truck box) ; tape up the last box, put it in the truck, and return the truck
(if (f book box) ; otherwise, if we can put the current book in the pending box
(recur truck (conj box book) books) ; put the book in the box and work on the next book
(recur (conj truck box) [book] books))))) ; otherwise, tape up the box, put it in the truck, and start a new box with the new book in it, and work on the next book
(def words ["or" "line" "important" "may" "life" "mountain" "went"
"change" "along" "water" "through" "just" "look" "because" "than" "into"
"three" "after" "does" "stop" "get" "eye" "small" "world" "carry" "play"
"all" "really" "before" "don't" "family" "river" "enough" "another" "came"
"number" "why" "might" "write" "must" "other" "air" "something" "even" "own"
"children" "in" "keep" "saw" "kind" "see" "without" "country" "left" "night"
"story" "about" "but" "cut" "at" "few" "question" "began" "almost" "let" "put"
"again" "side" "good" "four" "always" "mile" "soon" "know" "man" "should"
"live" "begin" "more"])
(partition-while #(< (+ (count %1) (apply + (map count %2))) 15) words) ;; partition into subsequences of no more than 14 characters
;; [["or" "line"] ["important" "may"] ["life" "mountain"] ["went" "change"]
;; ["along" "water"] ["through" "just"] ["look" "because"] ["than" "into" "three"]
;; ["after" "does" "stop"] ["get" "eye" "small"] ["world" "carry" "play"]
;; ["all" "really"] ["before" "don't"] ["family" "river"] ["enough" "another"]
;; ["came" "number" "why"] ["might" "write" "must"] ["other" "air"]
;; ["something" "even"] ["own" "children" "in"] ["keep" "saw" "kind" "see"]
;; ["without" "country"] ["left" "night" "story"] ["about" "but" "cut" "at"]
;; ["few" "question"] ["began" "almost" "let"] ["put" "again" "side"]
;; ["good" "four" "always"] ["mile" "soon" "know"] ["man" "should" "live"] ["begin"]]
(defn count-of-e [s] (count (filter #{\e} s)))
(partition-while (fn [elem part] (< (+ (count-of-e elem) (reduce + (map count-of-e part))) 5)) words) ;; make sure no partition has more than 4 e's
;; [["or" "line" "important" "may" "life" "mountain" "went" "change" "along"]
;; ["water" "through" "just" "look" "because" "than" "into"]
;; ["three" "after" "does" "stop"]
;; ["get" "eye" "small" "world" "carry" "play" "all" "really"]
;; ["before" "don't" "family" "river" "enough"]
;; ["another" "came" "number" "why" "might" "write" "must"]
;; ["other" "air" "something" "even" "own"]
;; ["children" "in" "keep" "saw" "kind"]
;; ["see" "without" "country" "left" "night" "story" "about" "but" "cut" "at" "few"]
;; ["question" "began" "almost" "let" "put" "again" "side" "good" "four" "always"]
;; ["mile" "soon" "know" "man" "should" "live" "begin"]]
@christoph-frick
Copy link

if you don't like the nested ifs, cond is an option too. decide for yourself:

(defn partition-while
  [f coll]
  (loop [truck []
         box [] 
         [book & books] coll]
    (cond 
      (empty? books) (conj truck box) 
      (f book box)   (recur truck (conj box book) books)
      :else          (recur (conj truck box) [book] books))))

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