2010-11-09 2 views
0

Итак, я пытаюсь изучить python самостоятельно и делаю головоломки для кодирования. Я наткнулся на одного, который в значительной степени просил, чтобы лучшая позиция стояла в очереди, чтобы выиграть конкурс. Человек, управляющий конкурсом, избавляется от людей, стоящих на нечетных позициях.Рекурсивный метод, возвращающий исходное значение

Так, например, если 1, 2, 3, 4, 5

Было бы избавиться от нечетных позиций, оставляя 2, 4

бы избавиться от остальных нечетных позиций, оставляя 4 в качестве победителя ,

Когда я отладки кода, кажется, работает, но это возвращение [1,2,3,4,5] вместо ожидаемого [4]

Вот мой код:

def findWinner(contestants): 
    if (len(contestants) != 1): 
     remainingContestants = [] 
     for i, contestant in enumerate(contestants, 1): 
      if (isEven(i)): 
       remainingContestants.append(contestant) 
     findWinner(remainingContestants) 
    return contestants 

я не вижу логическую ошибку или есть что-то еще, чего я не вижу?

ответ

3

Вы должны вернуть значение из рекурсии функции к функции вызывающего абонента:

return findWinner(remainingContestants) 

иначе вы бы возвращать только исходное значение без каких-либо изменений.

def findWinner(contestants): 
    if (len(contestants) != 1): 
     remainingContestants = [] 
     for i, contestant in enumerate(contestants, 1): 
      if (isEven(i)): 
       remainingContestants.append(contestant) 
     return findWinner(remainingContestants) # here the value must be return 
    return contestants # without the return above, it will just return this value(original) 
+0

А, это работает. Спасибо, я не уверен, что вы имеете в виду, мне все равно придется удалить четных соперников после того, как я удалю лишние? Я получаю ожидаемые результаты сейчас, и я не вижу ничего плохого в логике ... – Ryan

0

Вы пропускаете возвращение на линии, где вы называете «findWinner»

1

вы shold использовать

return findWinner(remaingContestants) 

иначе, конечно, список никогда не будет обновляться и поэтому ваши функ всегда будет возвращать содержащиеся в нем ссылки

однако см. PEP8 для руководства по стилю для кода питона: http://www.python.org/dev/peps/pep-0008/

FUNC ISEVEN, вероятно, является излишеством ... просто написать

if not num % 2 

наконец, рекурсии в Python не рекомендуется; сделать что-то вроде

def find_winner(alist): 
    while len(alist) > 1: 
     to_get_rid = [] 
     for pos, obj in enumerate(alist, 1): 
      if pos % 2: 
       to_get_rid.append(obj) 
     alist = [x for x in alist if not (x in to_get_rid)] 
    return alist 
3

Как об этом:

def findWinner(contestants): 
    return [contestants[2**int(math.log(len(contestants),2))-1]] 

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

или если не нравится «искусственное» решение и хотел бы фактически выполнить процесс:

def findWinner2(c): 
    while len(c) > 1: 
     c = [obj for index, obj in enumerate(c, 1) if index % 2 == 0] #or c = c[1::2] thanks desfido 
    return c 
+0

Я тестировал все различные решения, первый метод с математикой, безусловно, самый быстрый, второй способ, который вы написали, на самом деле второй - самый быстрый, слегка нарезанный позади него. Я, честно говоря, не понимаю математику за то, что вы сделали, хотя. Второй способ (и, альтернативно, метод desfido), я понимаю, что это не первое, о чем я думал, так как я буквально начал изучать python день или два назад. Спасибо за предложения! – Ryan

+0

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

+0

Каждый проход вы удаляете участников в нечетном положении и сокращаете пополам индексы в четном положении. Те, кто находится в положении более высокой степени 2 (2^4 = 16,2^5 = 32 и т. Д.), Могут быть уменьшены вдвое чаще, чем стать нечетными. Первый проход - исключить нечетные позиции (делимые на 2^0 == 1, не делящиеся на 2^1 == 2). Nth pass - исключить участников ORIGINALLY в положениях, делящихся на 2^n-1, но не 2^n. Итак ... log base 2 of len (c) означает найти x, где 2^x = len (c). Вероятно, это не целое число, поэтому получите целое число справа от него w/int (x). 2^int (x) является pos победителем, но мы вычитаем на 1, так как массив начинается с 0. –

1

Есть ли причина, что вы итерацию по списку вместо того, чтобы использовать кусочек? Кажется не очень python-y, чтобы не использовать их для меня.

Кроме того, вы можете сделать что-то разумное в случае пустого списка. Теперь вы перейдете в бесконечный цикл.

Я бы написать функцию

def findWinner(contestants): 
    if not contestants: 
     raise Exception 
    if len(contestants)==1: 
     return contestants[0] 
    return findWinner(contestants[1::2]) 

(сколько @ jon_darkstar указывают, что это немного по касательной к вопросу вы явно просят, но все еще хорошая практика, чтобы участвовать в том, что вы» re doing)

+0

ну и что? да, это хорошо, что они выяснили его рекурсию, но это тоже хорошо показать. этот фрагмент - фантастическая идея, лучше, чем список comp, который я сделал в своем втором примере. +1 (btw термин pythonic!) –

+0

Я понял, что есть более простой способ сделать это, ясно, что мне еще предстоит многому научиться с Python! Благодаря! – Ryan

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