Tung Nguyen
Tung Nguyen

Reputation: 149

How to limit the depth of recursion in python?

I have a list of elements. I want to know if there are two pairs of elements in the list, in which the elements of the pair have the same value.

My idea is that I first compare all the elements in the list, if a pair is found, remove the pair from the list, then proceed again. Thus I think I can use recursion to do this task, but limit the depth to 2 to solve the problem.

Here is my first try:

    recursion_depth=0
        def is_twopair(card):
            nonlocal recursion_depth
            if recursion_depth==2: return True
            for i in range(0, len(card)):
                for k in range(i+1,len(card)):
                    if card[i].value==card[k].value:
                        del card[k], card[i]
                        recursion_depth+=1
                        is_twopair(card)      
                    else: continue
                else: continue
            else: return False

I use the variable recursion_depth to record the the depth of recursion, but then realize that the return command doesn't immediately terminate the function and return true, but returns to its original caller is_twopair(card) instead. So my question is:

  1. Is there a way to immediately terminate the function and return the result true?
  2. Is there a way to limit the depth of recursion?

I know there maybe several ways to work around this. But I want to stay faithful to my idea and use this as an opportunity for learning.

Upvotes: 1

Views: 1674

Answers (3)

Jared Goguen
Jared Goguen

Reputation: 9010

I don't believe you can "break out" of the recursion without some serious black magic, nor do I believe that you should try to. Cascading the return value up the calling chain is typically a fine approach.

I'd personally avoid using a nonlocal variable and keep track of the recursion depth within the scope of each function call.

def remove_pairs(card, count=2, depth=0):
    if depth == count:
        return card

    for i in range(0, len(card)):
        for j in range(i+1, len(card)):
            if card[i].value == card[j].value:
                del card[j], card[i]
                return remove_pairs(card, count, depth+1) # add return here

Moving the tracking of the depth into the function itself will allow the function to be called repeatedly from different locations without issue.

Additionally, the code can be cleaned up some using itertools.combinations.

from itertools import combinations

def remove_pairs(cards, count=2, depth=0):
    if depth == count:
        return cards

    for card1, card2 in combinations(cards, 2):
        if card1.value == card2.value:
            cards.remove(card1)
            cards.remove(card2)
            return remove_pairs(cards, count, depth+1)

Upvotes: 2

Blckknght
Blckknght

Reputation: 104712

I think the piece you're missing is a return call to pass on the results of a recursive call back up to the previous caller:

if card[i].value==card[k].value:
    del card[k], card[i]
    recursion_depth+=1
    return is_twopair(card)       # add return here!

I don't really think recursion is a natural way to solve this problem, but with the above change, it should work. You could avoid needing to use a nonlocal variable by passing the depth as an optional parameter.

Upvotes: 0

Ika8
Ika8

Reputation: 391

yourList = [1,1,2,2,3,4]
yourDict = {}
for i in yourList:
    yourDict[i] = yourList.count(i)

This code will return the number of ocurrences for every value in the list so you can determinate the number of pairs..

In this case:

yourDict - - > {1: 2, 2: 2, 3: 1, 4: 1}

The value 1 appear 2 times, the value 2 appear 2 times, the value 3 and 4 appear 1 time.

Upvotes: 0

Related Questions