简体   繁体   中英

Python recursively jumping through a list by a given index jump or less while avoiding zeros

I am trying to write a function that has only one argument, a list of positive integers.

It has to be recursive and find whether you can get from the start to the end while avoiding landing on 0s. It has to start at first value list[0] but you can jump by either the full amount or less.

For example

list1 = [3,1,2,0,4,0,1]
list2 = [3,2,1,0,2,0,2]

List 1 should return True as you can jump from 3 to 2 to 4 to 1.

List 2 should return False as it does not matter how you jump, you will land at the first 0.

Here is my attempt so far:

def check_level(level):
    jump = level[0]
    if level[-1] == 0:
        return False
    elif jump == 0:
        return False
    
    elif jump == 0:
        return False
    
    elif len(level) > 1:
        if level[jump] > len(level):
            return True

        elif level[-1] == 0:
            return False
        
        elif level[0] != 0:
            if level[jump] == 0:
                level[0] -= 1
                return check_level(level)
            else:
                jump_index = level.index(level[jump])
                new_level = level[jump_index:]
                return check_level(new_level)

    else:
        return True

It does not work with all examples and with others it comes up with an error:

if level[jump] > len(level):
TypeError: '>' not supported between instances of 'list' and 'int'```

I am out of ideas on how to approach this and whether my approach is failed from the start... I hate recursion, hence I need to practice it.

The general logic is:

"If you can jump to a True position, the current position is also True"

Implemented like this:

def checklevel(lst):
    if not lst:
        # no list is True (we are done)
        return True  
    return any( checklevel(lst[i:]) for i in range(1,lst[0]+1))

list1 = [3,1,2,0,4,0,1]
list2 = [3,2,1,0,2,0,2]

assert checklevel(list1)
assert not checklevel(list2)

Note that this is a terrible solution for large lists, you should try a iterative dp-table in that case.

After advancing by a number of positions, you simply have to recurse with the rest of the list. Do it for distances from 1 to the value of the first element and you're done:

def jumpable(A):
    if not A: return True # reaching end wins
    return any(jumpable(A[i+1:]) for i in range(A[0])) # try all distances

ouput:

print(jumpable([3,1,2,0,4,0,1])) # True
print(jumpable([3,2,1,0,2,0,2])) # False

To avoid creating memory wasting temporary lists you can pass an index down (instead of a sublist) and use it as the starting point for the next level of recursion:

def jumpable(A,i=0):
    if i>=len(A) : return True # reaching end 
    return any(jumpable(A,i+j+1) for j in range(A[i])) # try all distances

With a default value for i=0, you function still has only one parameter when called from the outside.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM