Создайте таблицу Vigenère Cypher в Python

Я изо всех сил пытался создать таблицу vigenere в python. Результат должен быть:

Таблица шифров Виженера

Так что в основном у меня есть весь алфавит в первой строке, а алфавит сдвинут на одну букву во второй и т. д.

Это мой код до сих пор:

class CypherTable:

    def __init__(self):
        self.matrix = [[chr(i) for i in range(ord('a'),ord('z')+1)] for i in range(5)]

    def __str__(self):
        for i in range(len(self.matrix)):
            print self.matrix[i]
        return ""

table = CypherTable()
print(table)

Мне удалось напечатать буквы от a до z несколько раз, но я не знаю, как изменить каждое взаимодействие, чтобы сдвинуть первую букву на единицу. Я привык работать в java, где вы сначала определяете длину массива, а затем заполняете его, но, поскольку у python более быстрый синтаксис, я не могу понять, как это сделать лучше всего.


person Alex    schedule 18.11.2017    source источник
comment
Взгляните на эту ссылку. /   -  person Sreeram TP    schedule 18.11.2017


Ответы (2)


Более простой способ — использовать модуль string:

from string import ascii_uppercase as l

class CypherTable:
   def __init__(self):
      self.final_table = [l[i:]+l[:i] for i in range(len(l))]

for i in CypherTable().final_table:
    print(i)

Выход:

ABCDEFGHIJKLMNOPQRSTUVWXYZ
BCDEFGHIJKLMNOPQRSTUVWXYZA
CDEFGHIJKLMNOPQRSTUVWXYZAB
DEFGHIJKLMNOPQRSTUVWXYZABC
EFGHIJKLMNOPQRSTUVWXYZABCD
FGHIJKLMNOPQRSTUVWXYZABCDE
GHIJKLMNOPQRSTUVWXYZABCDEF
HIJKLMNOPQRSTUVWXYZABCDEFG
IJKLMNOPQRSTUVWXYZABCDEFGH
JKLMNOPQRSTUVWXYZABCDEFGHI
KLMNOPQRSTUVWXYZABCDEFGHIJ
LMNOPQRSTUVWXYZABCDEFGHIJK
MNOPQRSTUVWXYZABCDEFGHIJKL
NOPQRSTUVWXYZABCDEFGHIJKLM
OPQRSTUVWXYZABCDEFGHIJKLMN
PQRSTUVWXYZABCDEFGHIJKLMNO
QRSTUVWXYZABCDEFGHIJKLMNOP
RSTUVWXYZABCDEFGHIJKLMNOPQ
STUVWXYZABCDEFGHIJKLMNOPQR
TUVWXYZABCDEFGHIJKLMNOPQRS
UVWXYZABCDEFGHIJKLMNOPQRST
VWXYZABCDEFGHIJKLMNOPQRSTU
WXYZABCDEFGHIJKLMNOPQRSTUV
XYZABCDEFGHIJKLMNOPQRSTUVW
YZABCDEFGHIJKLMNOPQRSTUVWX
ZABCDEFGHIJKLMNOPQRSTUVWXY

Чтобы быть еще чище, особенно если вы не будете объявлять какие-либо другие методы в классе, вы можете использовать @classmethod:

from string import ascii_uppercase as l
class CypherTable:
    final_table = [l[i:]+l[:i] for i in range(len(l))]
    @classmethod
    def show_board(cls):
        for i in cls.final_table:
           print(i)

CypherTable.show_board()

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

from string import ascii_uppercase as l
class CypherTable:
   def __init__(self):
      self.final_table = [l[i:]+l[:i] for i in range(len(l))]
   def cross(self, b, a):
       val1 = self.final_table[0].index(a)
       new_letter = [i for i in self.final_table if i[0] == b][0][val1]
       return new_letter

c = CypherTable()
print(c.cross('P', 'C'))

Выход:

'R'
person Ajax1234    schedule 18.11.2017
comment
Извините, я, вероятно, не очень хорошо объяснил. Это похоже на одномерный список, поэтому я должен иметь доступ к этим элементам, чтобы найти соответствующую букву между двумя буквами. Например. P и C пересекаются в R, поэтому я должен иметь возможность [indexOfP][indexOfC] - person Alex; 18.11.2017
comment
@ Алекс, нет проблем, пожалуйста, посмотрите мое последнее редактирование и дайте мне знать, работает ли оно для вас. - person Ajax1234; 18.11.2017
comment
Отлично работает! Большое спасибо! Я не могу понять алгоритм, который вы использовали в перекрестном методе, хотя - person Alex; 18.11.2017
comment
@Alex Во-первых, метод берет первую строку final_table, которая является заголовком, и находит индекс второй переменной, переданной методу. Затем повторяется final_table, чтобы найти строку, которая начинается с первого значения, переданного в метод. Оттуда доступ к элементу из списка осуществляется через индексацию, и осуществляется доступ к индексу второй переменной, хранящейся в val1, которая является перекрестным значением. - person Ajax1234; 18.11.2017
comment
Это было очень умно, здорово! Это как бы эмулирует получение значения с использованием двух индексов в java, таких как [ i ] [ j ] Все понял! - person Alex; 18.11.2017
comment
@Alex: строка Python представляет собой список символов. Таким образом, одномерный список строк на самом деле представляет собой матрицу символов. - person Eric Duminil; 18.11.2017

Вот ваш код с минимальным количеством изменений. Вы можете использовать модуль для цикла от 26 до 0. Обратите внимание, что __str__ должен возвращать строку и ничего не печатать:

class CypherTable:

    def __init__(self):
        self.matrix = [[chr(ord('A') + (i + j) % 26) for i in range(26)] for j in range(5)]

    def __str__(self):
        return "\n".join('|'.join(row) for row in self.matrix)

table = CypherTable()
print(table)

Он выводит:

A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A
C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B
D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C
E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D
person Eric Duminil    schedule 18.11.2017