2017-02-16 6 views
0

У меня есть список элементов. Я хочу знать, есть ли в списке две пары элементов, в которых элементы пары имеют одинаковое значение.Как ограничить глубину рекурсии в python?

Моя идея состоит в том, что я сначала сравниваю все элементы в списке, если пара найдена, удалите пару из списка, а затем повторите попытку. Таким образом, я думаю, что я могу использовать рекурсию для выполнения этой задачи, но ограничить глубину до 2, чтобы решить проблему.

Вот моя первая попытка:

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 

Я использую переменную recursion_depth записать глубину рекурсии, но потом понимает, что команда возврата не сразу прекращает функцию и возвращает истину, но возвращается вместо этого его первоначальный вызывающий is_twopair (карточка). Поэтому мой вопрос:

  1. Есть ли способ немедленно прекратить действие функции и вернуть результат true?
  2. Есть ли способ ограничить глубину рекурсии?

Я знаю, что возможно несколько способов обойти это. Но я хочу оставаться верным своей идее и использовать ее в качестве возможности для обучения.

+1

Вы можете скопировать пример своего списка? – Ika8

+0

Мой список - это список объектов карточек классов, в которых моделируются карты в покере. Так, например: [TD, TH, KD, KH, QD]. (TD означает десять алмазов, TD означает десять сердец, KD означает King Diamond и т. Д.). Значение атрибута указывает одно из 13 возможных значений карты (2,3,4 ... 10, J, Q, K A). Но я не думаю, что это очень важно для вопроса. Проблема может быть задана в любых списках любых типов. Вышеприведенный список должен возвращать true (у нас есть две десятки карт, 2 король-карты) –

ответ

0

Я думаю, что часть вас не хватает является return вызова пройти по результатам рекурсивного вызова обратно к предыдущему абоненту:

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

Я не думаю, что рекурсия является естественным способом для решения этой проблемы, но с вышеуказанным изменением она должна работать. Вы можете избежать необходимости использовать переменную nonlocal, передав depth в качестве необязательного параметра.

+0

Я использую рекурсию, потому что я только что узнал ее и хочу применить ее в некотором роде. ;) –

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

Этот код будет возвращать количество вхождений для каждого значения в списке, так что вы можете детерминированное количество пара ..

В этом случае:

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

Значение 1 отображается 2 раза, значение 2 отображается 2 раза, значение 3 и 4 отображается 1 раз.

+0

Я не уверен, что это то, что имел в виду OP. Однако здесь гораздо короче способ сделать то, что вы сделали: 'из коллекций импорта Counter' ' счетчик = счетчик (yourList) ' –

+0

редактировать мой ответ, и я принимаю ваше решение – Ika8

+0

Это хороший способ сделать свою задачу , Спасибо за ответ ! Я хочу знать, возможен ли мой способ. –

1

Я не верю, что вы можете «вырваться» из рекурсии без серьезной черной магии, и я не верю, что вам следует попытаться. Каскадирование возвращаемого значения вверх по вызывающей цепочке, как правило, является прекрасным подходом.

Я бы лично избегал использования нелокальной переменной и отслеживал глубину рекурсии в рамках каждого вызова функции.

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 

Перемещение отслеживания глубины в саму функцию позволит многократно вызывать функцию из разных мест без проблем.

Кроме того, код можно очистить, используя 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) 
+0

Вот как я отслеживаю глубь, если пытаюсь проанализировать проблему производительности. Также хорошо знать о sys.setrecursionlimit(), но это больше для его увеличения, если вы знаете, что вам нужно какое-то конечное значение, немного превышающее значение по умолчанию (например, для некоторых алгоритмов динамического программирования). –

+0

Мне не нравится, как вы прерываете рекурсию на какой-то произвольной глубине, но все равно возвращаете значение. Это должно быть какое-то исключение. –

+0

@KennyOstrom Вопрос конкретно просит рекурсию прерываться на глубине 2. –

Смежные вопросы