Reputation: 149
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:
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
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
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
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