1

Given a list A and a size B:

A = [1, 2, 3, 4, 2]
B = 3

Expected output:

[[1, 2, 3], [2, 3, 4], [3, 4, 2], [4, 2, 1], [2, 1, 2]]

My [failing] solution:

def sol(A,B):
    return [A[i : i + B] for i in range(B + 1)]

My [failing] output:

[[1, 2, 3], [2, 3, 4], [3, 4, 2], [4, 2]]
ddejohn
  • 8,775
  • 3
  • 17
  • 30
abd
  • 155
  • 1
  • 9
  • Check the accepted answer in the duplicate link – U13-Forward Sep 19 '21 at 05:15
  • @U12-Forward without itertools i need – abd Sep 19 '21 at 05:32
  • from itertools import combinations, n = 3 x= [1, 2, 3 , 4, 2] list(combinations(x, n)) which is wrong because [(1, 2, 3), (1, 2, 4), (1, 2, 2), (1, 3, 4), (1, 3, 2), (1, 4, 2), (2, 3, 4), (2, 3, 2), (2, 4, 2), (3, 4, 2)] – abd Sep 19 '21 at 05:36
  • in above so many elements are there which is not sequence like (1,2,2) (2,3,2) etc – abd Sep 19 '21 at 05:36
  • What do you mean? `(1, 2, 2)` *is* in `A`... Why would `(1, 2, 2)` *not* be considered one of the subsequences of `A` but `(1, 2, 4)` *is*, according to your post? – ddejohn Sep 19 '21 at 05:40
  • What exactly is your definition of "combination" here? – ddejohn Sep 19 '21 at 05:41
  • @abd Do you mean by something like in my answer? – U13-Forward Sep 19 '21 at 05:43
  • @U12-Forward yes , but i need to add first two elements and last one element , also firs element and last two elements – abd Sep 19 '21 at 05:52
  • @ddejohn I want sequence combination, please see the answer by Code alpha – abd Sep 19 '21 at 05:54
  • Should `[1, 2, 4]` be `[4, 2, 1]` instead? Right now there is no discernible logic behind your desired output. – ddejohn Sep 19 '21 at 05:55
  • @ddejohn its just combination of continuous 3 elements, but i need first element + last 2 elements, first two elements + last element. its kind of cycle – abd Sep 19 '21 at 06:05
  • @ddejohn my bad, i have rectified it – abd Sep 19 '21 at 06:19

4 Answers4

2

You can get it as an iterator using cycle and islice from itertools:

A = [1, 2, 3, 4, 2]
B = 3

from itertools import cycle,islice

subIter = zip(A,*(islice(cycle(A),i,None) for i in range(1,B)))
for sub in subIter:
    print(sub)

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

Note that this is nothing more than a cute trick, it is not efficient and you should really go with something like ddejohn's solution.

or this variant of it:

[ A[i:i+B]+A[:max(0,i+B-len(A))] for i in range(len(A)) ]

Another solution would be to use deque from collections:

from collections import deque
from itertools import islice

A = [1, 2, 3, 4, 2]
B = 3

result = [ [*islice(q,q.rotate(-1),B)] 
           for q in [deque(A)] for _ in q.rotate() or A ]

print(result)
[[1, 2, 3], [2, 3, 4], [3, 4, 2], [4, 2, 1], [2, 1, 2]]
Alain T.
  • 40,517
  • 4
  • 31
  • 51
1

I think this will give your desired output:

def access(x, y, A):
    return [A[i] for i in range(x, y)]

def sol(A, B):
    return [access(i, i+B, A) for i in range(1-B, len(A)-B+1)]
Coder Alpha
  • 157
  • 1
  • 10
  • can you explain (1-B, B) – abd Sep 19 '21 at 05:54
  • So, you are looking for 3 numbers on the list which are appearing in a continuous sequence, and you need elements which are also warping on the ends of the list.... 1-B starts from the "4" in the list, and returns 3 elements from there, which also warps around the list (1-B to use negative indices, A[-2] points to 4). B is the ending as the final group needs to end in the last element (2). – Coder Alpha Sep 19 '21 at 05:57
  • The access function is present as statements like A[-2:1] give an empty list. – Coder Alpha Sep 19 '21 at 06:00
  • Edit: To make things more general, i have replaced (1-B,B) with (1-B, len(A)-B+1), which will give you the last group, [3, 4, 2], as i ends with 3, so the last access call is access(3, 6). – Coder Alpha Sep 19 '21 at 06:05
  • 1
    This will throw a `NameError` if `A` isn't defined globally. – ddejohn Sep 19 '21 at 06:10
  • I have amended the mistake... Thank you! – Coder Alpha Sep 19 '21 at 06:11
1

A slight variation on what's been posted, now that I understand what you're asking for:

def sol(x, n):
    wrap = x + x[:(n - 1)]
    return [wrap[i : i + n] for i in range(len(x))]

Explanation of wrap:

We can use slicing to add a copy of the first n - 1 elements of x to the end of x, which simulates "wrapping" back around to the front of the array. Here's an example using letters to make it clearer:

>>> n = 3
>>> x = "abcxyz"
>>> x + x[:(n - 1)]
'abcxyzab'

From there, you can take n-length slices of wrap to simulate "sliding" a window of width n across wrap:

abcxyz
^^^
abcxyz
 ^^^
abcxyz
  ^^^
abcxyz
   ^^^
abcxyz
^   ^^
abcxyz
^^   ^

Since fiddling with indices to wrap around to the front of x is tedious, we're simulating it with wrap:

abcxyzab
^^^
abcxyzab
 ^^^
abcxyzab
  ^^^
abcxyzab
   ^^^
abcxyzab
    ^^^
abcxyzab
     ^^^
ddejohn
  • 8,775
  • 3
  • 17
  • 30
0

If I understand correctly you mean:

>>> list(zip(*(A[i:] for i in range(B))))
[(1, 2, 3), (2, 3, 4), (3, 4, 2)]
>>> 
U13-Forward
  • 69,221
  • 14
  • 89
  • 114
  • This doesn't reflect OP's expected output though. It's hard to answer this question right now because their constraints seem to be inconsistent. – ddejohn Sep 19 '21 at 05:43
  • @ddejohn What I expect is that the OP means this. There is no logic to his desired output. – U13-Forward Sep 19 '21 at 05:43
  • its just combination of continuous 3 elements, but i need first element + last 2 elements, first two elements + last element.in addition to [(1, 2, 3), (2, 3, 4), (3, 4, 2)] its kind of cycle – abd Sep 19 '21 at 06:05