pythonlistalgorithmloops

Algorithm for detecting full loop when iterating over a list


Assignment:

Write a funcion cycle_sublist(lst, start, step) where:

  • lst is a list
  • start is number that satisfies: 0 <= start < len(lst)
  • step is the amount we increase your index each iteration

without using: slicing, importing, list comprehension, built-in functions like map and filter.

The function works in this way: We start to iterate over the list of items when we get back to start or cross it again. So for example:

cycle_sublist([1], 0, 2) -> [1]
cycle_sublist([6, 5, 4, 3], 0, 2) -> [6, 4]
cycle_sublist([7, 6, 5, 4, 3], 3, 1) -> [4, 3, 7, 6, 5]
cycle_sublist([4, 3, 2, 5, 1, 6, 9], 2, 2) -> [2, 1, 9, 3]
cycle_sublist([4, 3, 2, 5, 1, 6, 9], 5, 3) -> [6, 3, 1]

My problem is detecting when I have completed a cycle. I tried to:

None of those worked.

Here is my code - with the missing logic for detecting the cycle:

def cycle_sublist(lst,start,step):
    index = start 
    length = len(last)

    cycle_complete = False
    res = []

    while True:
        index = index % length if index >= length else index

        if ...:
            cycle_complete = True

        if cycle_complete and index >= start:
            break

        res.append(lst[index])

        index += step

    return res

If you can I'd like to ask you to answer with the algorithm to detect the cycle only so I can write the code myself.


Solution

  • This is my try based on your try. I got something like this:

    def cycle_sublist(lst,start,step):
        index = start 
        length = len(lst)
        res = []
    
        while index < length + start:
            res.append(lst[index % length])
            index += step
    
        return res
        
    print(cycle_sublist([1], 0, 2))                    # [1]
    print(cycle_sublist([6, 5, 4, 3], 0, 2))           # [6, 4]
    print(cycle_sublist([7, 6, 5, 4, 3], 3, 1))        # [4, 3, 7, 6, 5]
    print(cycle_sublist([4, 3, 2, 5, 1, 6, 9], 2, 2))  # [2, 1, 9, 3]
    print(cycle_sublist([4, 3, 2, 5, 1, 6, 9], 5, 3))  # [6, 3, 1]
    

    Basically, there is not much of a difference between your and my code. You were trying to keep index in valid range which made it more difficult to detect when cycle was over. Change I introduced is that I let index change in each iteration by step and not trying to keep it in valid range since I used remainder when indexing list. I guess you know, but remainder goes up to length - 1 so it will always be in valid range. Additionally, I removed some unused variables.

    Little addition, not sure if it's helpful. If you want to cycle multiple times under conditions you set, you can change while condition to while index < n * length + start: where n is how many times you want to cycle through list. Also, if you want to include starting element if final iteration sets on him, change < to <= in while condition.