Рекурсивный многосменный Цезарь-шифр - Ошибка типа (не может быть завершена Нет)

python recursion caesar-cipher

159 просмотра

1 ответ

Первый раз пишу здесь, новичок в python, но действительно наслаждаюсь тем, что я с ним делаю. Работа через MIT Open проблем с учебными программами на данный момент. Любые предложения других подобных ресурсов?

Моя проблема с возвратом рекурсивной функции, которая предназначена для построения списка многослойных сдвигов в виде кортежей, где находится каждый кортеж (начальное местоположение смещения, величина смещения). Сдвиг 5 изменит a на f, abcdef.

Код ниже для справки, но вам не нужно читать все это.

текст - это многослойный скремблированный ввод, например: 'grrkxmdffi jwyxechants idchdgyqapufeulij'

def find_best_shifts_rec(wordlist, text, start):

    ### TODO.

    """Shifts stay in place at least until a space, so shift can only start
    with a new word
    Base case? all remaining words are real

    Need to find the base case which goes at the start of the function to
    ensure it's all cleanly returned

    Base case could be empty string if true words are removed?
    Base case when start = end

    take recursive out of loop

    use other functions to simplify
    """


    shifts = []
    shift = 0


    for a in range(27):
        shift += 1
        #creates a string and only shifts from the start point
        """text[:start] + optional add in not sure how it'd help""" 
        testtext = apply_shift(text[start:],-shift)

        testlist = testtext.split()

        #counts how many real words were made by the current shift
        realwords = 0
        for word in testlist:
            if word in wordlist:
                realwords += 1

            else:
                #as soon as a non valid word is found i know the shift is not valid
                break
        if a == 27 and realwords == 0:
            print 'here\'s the prob'
        #if one or more words are real
        if realwords > 0:

            #add the location and magnitude of shift
            shifts = [(start,shift)]

            #recursive call - start needs to be the end of the last valid word
            start += testtext.find(testlist[realwords - 1]) + len(testlist[realwords - 1]) + 1

            if start >= len(text):

                #Base case
                return shifts
            else:
                return shifts + find_best_shifts_rec(wordlist,text,start)

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

    return shifts + find_best_shifts_rec(wordlist,text,start)
TypeError: can only concatenate list (not "NoneType") to list

эта ошибка для следующего в самом низу моего кода

else:
                return shifts + find_best_shifts_rec(wordlist,text,start)

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

РЕДАКТИРОВАТЬ:

Добавляя в конец:

elif a == 26: return [()]

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

Автор: Toby Howard Источник Размещён: 08.11.2019 11:24

Ответы (1)


0 плюса

Решение

Ниже моя попытка переделать ваш код, чтобы сделать то, что вы хотите. Конкретные изменения: уменьшен диапазон с 27 до 26, чтобы позволить циклу выйти естественным образом и вернуть пустой shiftsмассив; объединил aи shiftначал их с нуля, так что вернется незашифрованный текст [(0, 0)]; .find()логика испортит , если то же самое слово появляется в списке дважды, изменил его rindex()как бинт (т.е. последний правильно декодируются один, где вы хотите , чтобы начать, не первые).

def find_best_shifts_rec(wordlist, text, start=0):

    shifts = []

    for shift in range(26):

        # creates a string and only shifts from the start point
        testtext = apply_shift(text[start:], -shift)

        testlist = testtext.split()

        # words made by the current shift
        realwords = []

        for word in testlist:

            if word in wordlist:
                realwords.append(word)
            else:  # as soon as an invalid word is found I know the shift is invalid
                break

        if realwords:  # if one or more words are real

            # add the location and magnitude of shift
            shifts = [(start, shift)]

            # recursive call - start needs to be the end of the last valid word

            realword = realwords[-1]

            start += testtext.rindex(realword) + len(realword) + 1

            if start >= len(text):
                return shifts  # base case

            return shifts + find_best_shifts_rec(wordlist, text, start)

    return shifts

'lbh fwj hlzkv tbizljb'

Автор: cdlane Размещён: 20.08.2016 04:19
Вопросы из категории :
32x32