Площадь кода, кодирования и декодирования


Я делаю какой-либо Python-практика и написал квадратных кода кодер/декодер. Как описано в сверла #4 из программирования практика, проблемы, персонажей, сообщения пишутся слева направо на квадратной сетке, и каждая строка кодированного сообщения читать, идя сверху вниз.

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

import math


def encode(message):
    message = message.replace(" ", "")
    square = math.ceil(math.sqrt(len(message)))

    # Create the "grid"
    rows = []
    for row in range(square):
        pos = row * square
        code = message[pos:pos + square]
        rows.append(code)

    print("The grid:\n{}".format("\n".join(rows)))

    # Encode the message
    coded_msg = ""
    for col in range(square):
        for row in range(square):
            # The last column of the last row will throw an out of range error, so handle that
            if col < len(rows[row]):
                coded_msg += rows[row][col]
        coded_msg += " "

    return coded_msg.rstrip()


def decode(message):
    square = math.sqrt(len(message))
    col_count = math.ceil(square)
    row_count = math.ceil(len(message) / col_count)

    cols = message.split(" ")

    decoded_msg = ""
    for row in range(row_count):
        for col in cols:
            if row < len(col):
                decoded_msg += col[row]

    return decoded_msg


if __name__ == "__main__":

    print("Gimme a message:")
    in_message = input()

    coded_message = encode(in_message)
    print("--\nSquare message:\n{}".format(coded_message))
    decoded_message = decode(coded_message)
    #print("--\nDecoded message:\n{}".format(decoded_message))

    print("--\ninput: {}\noutput: {}".format(in_message, decoded_message))


159
2
задан 3 апреля 2018 в 07:04 Источник Поделиться
Комментарии
2 ответа

В обоих кодера и декодера, добавить один символ в результирующую строку, используя +=. Это плохая привычка для выполнения: так как строки в Python являются неизменными, добавляя символ означает выделение новую строку, затем копировать старое содержимое строки плюс суффикс.


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

Первая уловка отметить, что в Python строки представляют собой последовательности, и поэтому поддержка нарезки с помощью s[i:j:k] операции для извлечения каждого к- го символа:


Фрагмент из х с я к Дж с шагом к определяется как последовательность элементов с индексами x = i + n*k такие, что 0 <= n < (j-i)/k. Другими словами, индексы i, i+k, i+2*k, i+3*k и так далее, останавливаясь, когда Джей будет достигнут (но не включая Дж). Если к положительно, я и Джей сводятся к лен(ы), если они больше. ... Если я или Джей опущены или Noneони становятся “конечного” значения (которое зависит от знака к).

Во-вторых, всякий раз, когда вы видите картины, как:

array = []
for … in …:
array.append(…)

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

В этом случае, вы хотите присоединиться к кучке слова, используя пробел в качестве разделителя. Итак, вам нужно написать его как ' '.join(<em>some generator expression producing the columns</em>).

import math

def encode(plaintext):
plaintext = plaintext.replace(" ", "")
size = math.ceil(math.sqrt(len(plaintext)))
return ' '.join(plaintext[i::size] for i in range(size))


Для реализации дешифратора, вам не нужно делать никаких арифметических действий. Хитрость здесь заключается в использовании itertools.zip_longest(*cols) транспонировать матрицу и дать вам строки.

Опять же, я рекомендую использовать ''.join(…) С некоторым генератор выражений.

from itertools import zip_longest

def decode(ciphertext):
cols = ciphertext.split(" ")
return ''.join(''.join(c for c in row if c) for row in zip_longest(*cols))

2
ответ дан 4 апреля 2018 в 06:04 Источник Поделиться

Пару указателей.

В целом это хорошая практика, чтобы избежать поставив ничего другого, кроме вызова другой функции (например, main()) в if __name__ == "__main__" функция, просто, чтобы помочь облегчить модульного тестирования.

Строки документа для функции также неплохо иметь:

def foo():
'''This function does foo-all, always returns None'''
pass

Хороший (иш) один вкладыш для функции декодирования может быть что-то вроде этого:

def encode(message):
message = message.replace(" ", "")
length = math.ceil(math.sqrt(len(message)))
''.join(message[i::length] i in range(length))

Хотя я признаю, что он должен немного рефакторинга, как его немного долго для одной линии (редактирование адаптирован очень хорошее улучшение по сравнению с 200_success 'ы ответ, который они хорошо объясняют). Это показывает, что вы можете пропустить хоть построении сетки.

2
ответ дан 3 апреля 2018 в 11:04 Источник Поделиться