Как использовать рекурсию в python

#python #python-3.x

#python #python-3.x

Вопрос:

Я пытаюсь решить проблему, которая стимулирует движения робота. Робот начинается с позиции (0, 0, ‘N’). Команда задается в виде списка строк. функция ‘turn’ превращается из N в E, из S в W и обратно в N. Функция перемещения перемещается в определенном направлении: N, S по оси y и E, W по оси x. N: y 1 S: y-1 W: x-1 E: x 1

Часть, с которой у меня возникают проблемы, заключается в том, что при попытке использовать ярлыки в функции. Использование ‘turnleft’ вместо [‘turn’, ‘turn’, ‘turn’], ‘turnright’ вместо ‘turn’

 def macro_interpreter(code, macros):
 

при вызове функции:

 print(macro_interpreter(['turnleft', 'turnright'], {'turnleft': ['turn', 'turn', 'turn'], 'turnright' : ['turn'], 'bigleftturn' : ['move', 'move', 'turnleft', 'move', 'move'], 'bigrightturn' : ['move', 'move', 'turnright', 'move', 'move']}))
 

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

 def macro_interpreter(code, macros):
    x,y,index = 0, 0, 0
    state = ['N', 'E', 'S', 'W']
    for command in code:
        if command in macros:
            return macro_interpreter(macros[command], macros)
        else:
            if command == 'move':
                if state[index] == 'N':
                    y  = 1
                elif state[index] == 'E':
                    x  = 1
                elif state[index] == 'S':
                    y -= 1
                elif state[index] == 'W':
                    x -= 1
            elif command == 'turn':
                try:
                    index = index   1
                except IndexError:
                    index = 0
    return (x, y, state[index])            
 

Комментарии:

1. каков ваш ожидаемый результат?. насколько я могу видеть turn , он отсутствует в вашем макросе (при втором запуске) и 'move' также не был частью возвращаемых кодов, поэтому другие условия в этом блоке никогда не будут выполняться…. а также увеличение числа никогда не приведет к увеличению IndexError , скорее, попытка получить доступ к списку с отсутствующим индексом приведет.

Ответ №1:

Если вы всегда нажимаете один else оператор в цикле поверх code команд, то вы никогда не будете повторять, потому command not in macros что .

После первой итерации, code == ['turn', 'turn', 'turn'] , но macros не содержит ключа "turn"


Если вы хотите сделать это более правильно, то вы можете передать x, y и «состояние индекса направления» в качестве параметров функции, затем увеличить / изменить их в рекурсивном вызове, а не только изменять локальные переменные функции и всегда перезапускать их обратно на (0,0, 0).

Кроме того, вам нужно заменить это try except на index = (index 1) % len(state) , потому что при увеличении числа ошибка IndexError не будет обнаружена


Итак, что-то вроде этого

 state = ['N', 'E', 'S', 'W']
def macro_interpreter(code, macros, x=0,y=0,index=0):
    # TODO: check if x or y have gone outside "the board" 
        # TODO: return to break from recursion 

    for command in code:
        if command in macros:
            return macro_interpreter(macros[command], macros,x,y,index)
        else:
            if command == 'move':
                if state[index] == 'N':
                    return macro_interpreter(code[1:], macros,x,y=y 1,index)
 

Ответ №2:

Есть некоторые поправки, которые я внес в ваш код, чтобы правильно поддерживать рекурсию. Этот код будет делать то, чего вы хотите достичь.

 def macro_interpreter(code, macros, x=0, y=0, index=0):
    state = ['N', 'E', 'S', 'W']
    for command in code:
        if command in macros:
            x, y, curr_state = macro_interpreter(macros[command], macros, x, y, index)   
            # update new index with new state value         
            index = state.index(curr_state)
        else:
            if command == 'move':
                if state[index] == 'N':
                    y  = 1
                elif state[index] == 'E':
                    x  = 1
                elif state[index] == 'S':
                    y -= 1
                elif state[index] == 'W':
                    x -= 1
            elif command == 'turn':                
                index = (index   1)%len(state)
    return (x, y, state[index])   
 

Теперь, если я запущу ваш тестовый пример

 >> print macro_interpreter(['turnleft', 'turnright'], {'turnleft': ['turn', 'turn', 'turn'], 'turnright' : ['turn'], 'bigleftturn' : ['move', 'move', 'turnleft', 'move', 'move'], 'bigrightturn' : ['move', 'move', 'turnright', 'move', 'move']})
 Output:- (0, 0, 'N')
 

Я надеюсь, что это поможет вам.

Ответ №3:

Строка

 return macro_interpreter (macros etc.
 

будет делать именно это. Он покинет цикл for и вернется из внешнего вызова. Конец истории.

Ответ №4:

Я подозреваю, что это потому, что вы возвращаете

 macro_interpreter(macros[command], macros)
 

Это просто завершает работу функции после запуска рекурсивного кода. Ты увидишь, если изменишься

 return macro_interpreter(macros[command], macros)
 

Для

 print macro_interpreter(macros[command], macros)
 

что код будет печатать то, что вы хотите, чтобы он делал. Как вы хотите на самом деле обрабатывать выходные данные, зависит от вас.