fork download
  1. (set! *unchecked-math* true)
  2.  
  3. (defn grep-n-chunk [^long n f coll]
  4. (lazy-seq
  5. (when-let [s (seq coll)]
  6. (if (and (chunked-seq? coll) (> (count (chunk-first coll)) (+ 1 (* 2 n)))) ;; :(
  7. (let [fchunk (chunk-first coll)
  8. c (count fchunk)
  9. pred (chunk-buffer n)
  10. matches (chunk-buffer c)
  11. after (chunk-buffer n)]
  12. (loop [i 0 last-match-idx nil]
  13. (if (< i c)
  14. (let [x (nth fchunk i)]
  15. (if (and last-match-idx (<= i (+ n last-match-idx)))
  16. (do (chunk-append after x) (recur (inc i) last-match-idx))
  17. (if (f x)
  18. (do (chunk-append matches x)
  19. (dotimes [step n]
  20. (let [pred-match (nth fchunk (dec (- i step)) ::nil)]
  21. (when (not= pred-match ::nil)
  22. (chunk-append pred pred-match))))
  23. (recur (inc i) i))
  24. (recur (inc i) last-match-idx))))))
  25. (->> (grep-n-chunk n f (chunk-rest coll))
  26. (chunk-cons (chunk after))
  27. (chunk-cons (chunk matches))
  28. (chunk-cons (chunk pred))))
  29. (let [p (take-while (complement f) (take n s))
  30. n-till-first-match (count p)
  31. matches (take-while f (nthrest s n-till-first-match))]
  32. (if (seq matches)
  33. (let [n-till-last-match (+ (count p) (count matches))
  34. a (take n (nthrest s n-till-last-match))]
  35. (if (some f a)
  36. (concat p matches (grep-n-chunk n f (nthrest s n-till-last-match)))
  37. (concat p matches a (grep-n-chunk n f (nthrest s (+ n-till-last-match (count a)))))))
  38. (grep-n-chunk n f (rest s))))))))
  39.  
  40.  
  41. (defn sample [] (doall (grep-n-chunk 2 #(.get #{1 1111 1111111} %) (range 100000000))))
  42. (time (sample))
Success #stdin #stdout 4.98s 128076KB
stdin
Standard input is empty
stdout
"Elapsed time: 3822.715114 msecs"