This function comes from some code to calculate convolutions of finite sequences.
window n k = [ drop (i-k) $ take i $ [1..n] | i <- [1..(n+k)-1] ]
*Main> window 4 6
[[1],[1,2],[1,2,3],[1,2,3,4],[1,2,3,4],[1,2,3,4],[2,3,4],[3,4],[4]]
It's sliding window of length k
over a sequence of length n
, where k
can be larger than n
.
The code calls take
and drop
on the source list roughly n+k
times, so it seems to have at least quadratic complexity.
Clearly, it can be written without a list comprehension:
window n k = map (\i -> (drop (i-k) . take i) [1..n]) [1..(n+k)-1]
Is there a better way to do this?
Edit: Full set of examples, as requested.
Prelude> window 4 4
[[1],[1,2],[1,2,3],[1,2,3,4],[2,3,4],[3,4],[4]]
Prelude> window 4 6
[[1],[1,2],[1,2,3],[1,2,3,4],[1,2,3,4],[1,2,3,4],[2,3,4],[3,4],[4]]
Prelude> window 6 4
[[1],[1,2],[1,2,3],[1,2,3,4],[2,3,4,5],[3,4,5,6],[4,5,6],[5,6],[6]]
Computing the convolution of [1..4]
and [1..5]
works like this:
Prelude> let a = window 4 5
Prelude> let b = window 5 4
Prelude> map sum $ zipWith (zipWith (*)) a (map reverse b)
[1,4,10,20,30,34,31,20]