(ns grep-n)
(use 'clojure.test)
(defn grep-n [n f coll]
(lazy-seq
(when-let [s (seq coll)]
(let [p (take-while (complement f) (take n s))
n-till-first-match (count p)
matches (take-while f (nthrest s n-till-first-match))]
(if (seq matches)
(let [n-till-last-match (+ (count p) (count matches))
a (take n (nthrest s n-till-last-match))]
(if (some f a)
(concat p matches (grep-n n f (nthrest s n-till-last-match)))
(concat p matches a (grep-n n f (nthrest s (+ n-till-last-match (count a)))))))
(grep-n n f (rest s)))))))
(deftest grep-n-test
(is (= '(0 1 2)
(grep-n 1 #{1} (range 10))))
(is (= '(2 3 4)
(grep-n 1 #{3} (range 10))))
(is (= '(4 5 6 7 8)
(grep-n 2 #{6} (range 10))))
(is (= '(3 4 5 6 7 12 13 14 15 16)
(grep-n 2 #{5 14} (range 20))))
(is (= '(0 1 2 3 4 5 6 7 8)
(grep-n 3 #{3 5} (range 10))))
(is (= '(4 5 6)
(grep-n 2 #{4} (range 4 10))))
(is (= '(3 4 5 6 7)
(grep-n 2 #(= 0 (mod % 5)) (range 1 10)))))
(run-tests)
(time (doall
(take
10 (grep
-n
2 #{1 1111 1111111} (range 100000000)))))
KG5zIGdyZXAtbikKKHVzZSAnY2xvanVyZS50ZXN0KQogCihkZWZuIGdyZXAtbiBbbiBmIGNvbGxdCiAgKGxhenktc2VxCiAgICh3aGVuLWxldCBbcyAoc2VxIGNvbGwpXQogICAgIChsZXQgW3AgKHRha2Utd2hpbGUgKGNvbXBsZW1lbnQgZikgKHRha2UgbiBzKSkKICAgICAgICAgICBuLXRpbGwtZmlyc3QtbWF0Y2ggKGNvdW50IHApCiAgICAgICAgICAgbWF0Y2hlcyAodGFrZS13aGlsZSBmIChudGhyZXN0IHMgbi10aWxsLWZpcnN0LW1hdGNoKSldCiAgICAgICAoaWYgKHNlcSBtYXRjaGVzKQogICAgICAgICAobGV0IFtuLXRpbGwtbGFzdC1tYXRjaCAoKyAoY291bnQgcCkgKGNvdW50IG1hdGNoZXMpKQogICAgICAgICAgICAgICBhICh0YWtlIG4gKG50aHJlc3QgcyBuLXRpbGwtbGFzdC1tYXRjaCkpXQogICAgICAgICAgIChpZiAoc29tZSBmIGEpCiAgICAgICAgICAgICAoY29uY2F0IHAgbWF0Y2hlcyAoZ3JlcC1uIG4gZiAobnRocmVzdCBzIG4tdGlsbC1sYXN0LW1hdGNoKSkpCiAgICAgICAgICAgICAoY29uY2F0IHAgbWF0Y2hlcyBhIChncmVwLW4gbiBmIChudGhyZXN0IHMgKCsgbi10aWxsLWxhc3QtbWF0Y2ggKGNvdW50IGEpKSkpKSkpCiAgICAgICAgIChncmVwLW4gbiBmIChyZXN0IHMpKSkpKSkpCiAKKGRlZnRlc3QgZ3JlcC1uLXRlc3QKICAoaXMgKD0gJygwIDEgMikKICAgICAgICAgKGdyZXAtbiAxICN7MX0gKHJhbmdlIDEwKSkpKQogCiAgKGlzICg9ICcoMiAzIDQpCiAgICAgICAgIChncmVwLW4gMSAjezN9IChyYW5nZSAxMCkpKSkKIAogIChpcyAoPSAnKDQgNSA2IDcgOCkKICAgICAgICAgKGdyZXAtbiAyICN7Nn0gKHJhbmdlIDEwKSkpKQogCiAgKGlzICg9ICcoMyA0IDUgNiA3IDEyIDEzIDE0IDE1IDE2KQogICAgICAgICAoZ3JlcC1uIDIgI3s1IDE0fSAocmFuZ2UgMjApKSkpCiAKICAoaXMgKD0gJygwIDEgMiAzIDQgNSA2IDcgOCkKICAgICAgICAgKGdyZXAtbiAzICN7MyA1fSAocmFuZ2UgMTApKSkpCiAKICAoaXMgKD0gJyg0IDUgNikKICAgICAgICAgKGdyZXAtbiAyICN7NH0gKHJhbmdlIDQgMTApKSkpCiAKICAoaXMgKD0gJygzIDQgNSA2IDcpCiAgICAgICAgIChncmVwLW4gMiAjKD0gMCAobW9kICUgNSkpIChyYW5nZSAxIDEwKSkpKSkKIAoocnVuLXRlc3RzKQoKKHRpbWUgKGRvYWxsICh0YWtlIDEwIChncmVwLW4gMiAjezEgMTExMSAxMTExMTExfSAocmFuZ2UgMTAwMDAwMDAwKSkpKSk=