Given two integers m and n, where m >= n, how can you create a generator to return all the sliding windows?

Viewed 100

To clarify consider two strings, one of length m and the other of length n.

As an example m = 3 and n = 2, with s1 = abc and s2 = de.

First we compare:

 abc 
de
and generate tuple (0, 1) (as a and e are being compared, so give their indices)
then slide string s2

 abc 
 de
generate (0, 0) {compare a and d} 
generate (1, 1) {compare b and e}
 slide string s2

 abc 
  de
generate (1, 0) {compare b and d} 
generate (2, 1) {compare c and e}
 slide string s2

 abc 
   de
generate (2, 0) {compare c and d} 

so we return generate (0, 1), (0, 0), (1, 1), (1, 0), (2, 1), (2, 0) in that order

If for example m = 2 and and n = 2

we would generate (0, 1), (0, 0), (1, 1), (1, 0) using a same method of sliding the smaller string.

2 Answers
out = (
    (i1, i2)
    for anchor in range(n-1, -m, -1)
    for i1, i2 in enumerate(range(anchor, n))
    if 0 <= i1 < m and 0 <= i2 < n
)

testing

for m, n in [(3, 2), (2, 2), (5, 3)]:
    out = (
        (i1, i2)
        for anchor in range(n-1, -m, -1)
        for i1, i2 in enumerate(range(anchor, n))
        if 0 <= i1 < m and 0 <= i2 < n
    )
    print(*out, '', sep='\n')

Output

(0, 1)
(0, 0)
(1, 1)
(1, 0)
(2, 1)
(2, 0)

(0, 1)
(0, 0)
(1, 1)
(1, 0)

(0, 2)
(0, 1)
(1, 2)
(0, 0)
(1, 1)
(2, 2)
(1, 0)
(2, 1)
(3, 2)
(2, 0)
(3, 1)
(4, 2)
(3, 0)
(4, 1)
(4, 0)

You can do:

m = 3
n = 2

gen = ((j+i, j) 
       for i in range(1-n, m)
       for j in range(max((0, -i)), min((n, m-i))))

for t in gen:
    print(t)

giving:

(0, 1)
(0, 0)
(1, 1)
(1, 0)
(2, 1)
(2, 0)

Here:

  • i is the offset between the first characters of the two strings (going from -1 to 2 in that order in your example)
  • j is the index in the second string (s2)
Related