Попытка решить проблему числа с мнемоникой с помощью рекурсии

Для заданного строкового номера телефона ненулевой длины напишите функцию, которая возвращает все мнемоники для этого номера телефона в любом порядке.

`

def phoneNumberMnemonics(phoneNumber, Mnemonics=[''], idx=0):
    number_lookup = {'0':['0'], '1':['1'], '2':['a','b','c'], '3':['d','e','f'], '4':['g','h','i'], '5':['j','k','l'], '6':['m','n','o'], '7':['p','q','r','s'], '8':['t','u','v'], '9':['w','x','y','z']}

    if idx==len(phoneNumber):
        return Mnemonics
    else:
        new_Mnemonics=[]
        for letter in number_lookup[phoneNumber[idx]]:
            for mnemonic in Mnemonics:
                new_Mnemonics.append(mnemonic+letter)
        phoneNumberMnemonics(phoneNumber, new_Mnemonics, idx+1)
        

`

Если я использую ввод «1905», моя функция выводит ноль. Используя оператор печати прямо перед оператором возврата, я вижу, что мнемоника списка

['1w0j', '1x0j', '1y0j', '1z0j', '1w0k', '1x0k', '1y0k', '1z0k', '1w0l', '1x0l', '1y0l', '1z0l']

Какой правильный ответ. Почему возвращается ноль?

Я не очень хорошо разбираюсь в рекурсии (пока?), ваша помощь приветствуется.

Если вы не используете оператор return, ничего не возвращается.

Gene 02.11.2022 03:52

Спасибо @Gene за ваш ответ. У меня есть оператор return в пятой строке. Не уверен, что понимаю, что не так.

trying2learn 02.11.2022 04:05

этот вопрос лучше решить без рекурсии.

D.L 02.11.2022 21:55

@D.L, не могли бы вы объяснить, почему? Вы имеете в виду, потому что он добавляет O (n) памяти из-за стека вызовов, или есть другая причина?

trying2learn 03.11.2022 22:49

@ trying2learn, да, это в значительной степени так, плюс, как правило, он медленнее, чем голый цикл for или while. Одна глава этой книги конкретно посвящена рекурсии и рекурсивным процессам: amazon.co.uk/dp/B0BHL2XKCR, которая может быть вам полезна.

D.L 03.11.2022 23:12
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
5
68
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Правильный список (мнемоника) был сгенерирован для самого глубокого вызова рекурсии. Однако он не был передан обратно на предыдущие вызовы.

Чтобы исправить это, мнемоника не только должна быть возвращена в блоке «else», но также должна быть установлена ​​равной выходу рекурсивной функции phone Number Mnemonics.

def phoneNumberMnemonics(phoneNumber, Mnemonics=[''], idx=0):
number_lookup = {'0':['0'], '1':['1'], '2':['a','b','c'], '3':['d','e','f'], '4':['g','h','i'], '5':['j','k','l'], '6':['m','n','o'], '7':['p','q','r','s'], '8':['t','u','v'], '9':['w','x','y','z']}

print(idx, len(phoneNumber))
if idx==len(phoneNumber):
    pass
else:
    new_Mnemonics=[]
    for letter in number_lookup[phoneNumber[idx]]:
        for mnemonic in Mnemonics:
            new_Mnemonics.append(mnemonic+letter)
    Mnemonics=phoneNumberMnemonics(phoneNumber, new_Mnemonics, idx+1)
return Mnemonics

Я все еще чувствую, что мне не хватает изощренности в моем понимании рекурсии. Советы, отзывы и разъяснения приветствуются.

Ответ принят как подходящий

Существуют различные рекурсивные выражения этой проблемы, но самое простое, о чем стоит подумать, когда вы начинаете, — это «чисто функциональное». Это означает, что вы никогда не изменяете рекурсивно определенные значения. Скорее вычисляйте новые новые: списки и т. д. (Python не дает вам выбора в отношении строк; они всегда неизменяемы.) Таким образом, вы можете думать только о значениях, а не о том, как они хранятся и что их изменяет, что чрезвычайно подвержен ошибкам.

Чисто-функциональный способ думать об этой проблеме таков:

  • Если номер телефона представляет собой пустую строку, то возвращаемое значение представляет собой просто список, содержащий пустую строку.

  • В противном случае разбейте число на его первый символ и остальные. Рекурсивно получить все мнемоники R остальных. Затем найдите все буквы, соответствующие первой, и добавьте каждую из них к каждому члену R, чтобы создать новую строку (это называется декартовым векторным произведением, которое часто встречается в рекурсии). Верните все эти строки.

В этом выражении чистая функция имеет вид

M(n: str) -> list[str]:

Он принимает строку цифр и возвращает список мнемоник.

Вложить эту мысль в python довольно просто:

LETTERS_BY_DIGIT = {
  '0':['0'],
  '1':['1'],
  '2':['a','b','c'],
  '3':['d','e','f'],
  '4':['g','h','i'],
  '5':['j','k','l'],
  '6':['m','n','o'],
  '7':['p','q','r','s'],
  '8':['t','u','v'],
  '9':['w','x','y','z'],
}

def mneumonics(n: str):
  if len(n) == 0:
    return ['']
  rest = mneumonics(n[1:])
  first = LETTERS_BY_DIGIT[n[0]]
  rtn = []  # A fresh list to return.
  for f in first:  # Cartesian cross:
    for r in rest: #   first X rest
      rtn.append(f + r);  # Fresh string
  return rtn

print(mneumonics('1905'))

Обратите внимание, что этот код вообще не изменяет рекурсивные возвращаемые значения rest. Он создает новый список новых строк.

Когда вы освоите все идиомы Python, вы увидите более изящный способ кодировать одно и то же:

def mneumonics(n: str):
  return [''] if len(n) == 0 else [
    c + r for c in LETTERS_BY_DIGIT[n[0]] for r in mneumonics(n[1:])]

Является ли это наиболее эффективным кодом для решения этой проблемы? Точно нет. Но в любом случае это не очень практично. Лучше найти простое, правильное решение, которое легко понять, чем беспокоиться об эффективности, пока вы не освоите этот способ мышления.

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

Большое спасибо за ваше руководство. Существуют ли общие рекомендации, когда рекурсия является хорошим выбором?

trying2learn 04.11.2022 04:48

Эмпирическое правило: всякий раз, когда 1) это самый простой/самый естественный способ решения проблемы и 2) он непреднамеренно не увеличивает асимптотически более высокие затраты во время выполнения или хранения. Это решение нарушает 2), потому что оно копирует каждый список и каждую строку на каждом уровне рекурсии. Но для небольших строк это не имеет значения.

Gene 04.11.2022 04:54

Другие вопросы по теме