jobechoi
jobechoi

Reputation: 69

Can you for loop completely through a range, but starting from the nth element?

I would like to know if there exists a base solution to do something like this:

for n in range(length=8, start_position= 3, direction= forward)

The problem I'm encountering is I would like the loop to continue past the final index, and pick up again at idx =0, then idx=1, etc. and stop at idx= 3, the start_position.

To give context, I seek all possible complete solutions to the n-queen problem.

Upvotes: 1

Views: 87

Answers (5)

Adam Smith
Adam Smith

Reputation: 54163

You could implement this for an arbitrary iterable by using itertools.cycle.

from itertools import cycle

def circular_iterator(iterable, skip=0, length=None, reverse=False):
    """Produces a full cycle of @iterable@, skipping the first @skip@ elements
    then tacking them on to the end.

    if @iterable@ does not implement @__len__@, you must provide @length@
    """

    if reverse:
        iterable = reversed(iterable)

    cyc_iter = cycle(iterable)
    for _ in range(skip):
        next(cyc_iter, None)

    if length:
        total_length = length
    else:
        total_length = len(iterable)

    for _ in range(total_length):
        yield next(cyc_iter, None)

>>> lst = [x for x in range(1, 9)]
# [1, 2, 3, 4, 5, 6, 7, 8]

>>> list(circular_iterator(lst, skip=3))
[4, 5, 6, 7, 8, 1, 2, 3]

Upvotes: 0

ShlomiF
ShlomiF

Reputation: 2895

def loop_around_range(length, start_position, direction='forward'):
    looped_range = [k % length for k in range(start_position, start_position+length)]
    if direction == 'forward':
         return looped_range
    else:
         return looped_range[::-1]

Upvotes: 0

templatetypedef
templatetypedef

Reputation: 372724

Another option for solving this is to use modular arithmetic. You could do something like this, for example:

for i in range(8)
   idx = (i + 3) % 8
   # use idx

This easily can be generalized to work with different lengths and offsets.

Upvotes: 1

DYZ
DYZ

Reputation: 57033

Based on your latest edit, you need a "normal" range and the modulo operator:

for i in range(START, START + LEN): 
    do_something_with(i % LEN)

Upvotes: 5

Michael Butscher
Michael Butscher

Reputation: 10959

from itertools import chain

for n in chain(range(3,8), range(3)):
    ...

The chain() returns an iterator with 3, 4, ..., 7, 0, 1, 2

Upvotes: 3

Related Questions