【问题标题】:Generate Vigenère Cypher table in Python在 Python 中生成 Vigenère Cypher 表
【发布时间】:2018-05-02 07:36:39
【问题描述】:

我一直在努力在 python 中创建 vigenere 表 结果应该是这样的:

所以基本上我的第一行有整个字母表,第二行的字母表移动了一个字母,等等。

到目前为止,这是我的代码:

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 具有更快的语法,我无法弄清楚最好的方法是什么。

【问题讨论】:

标签: python vigenere


【解决方案1】:

更简单的方法是使用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'

【讨论】:

  • 对不起,我可能没有很好地解释自己这似乎是一个一维列表,因此我应该能够访问这些元素以便找到两个字母之间的对应字母。 P 和 C 在 R 中交叉,所以我应该能够 [indexOfP][indexOfC]
  • @Alex 没问题,请查看我最近的编辑,如果它适合你,请告诉我。
  • 完美运行,非常感谢!虽然我无法真正理解您在交叉方法中使用的算法
  • @Alex 首先,该方法获取final_table 的第一行,即“标题”,并找到传递给该方法的第二个变量的索引。然后,final_table 被迭代以找到以传递给方法的第一个值开头的行。从那里,通过索引访问列表中的元素,并访问存储在val1 中的第二个变量的索引,即交叉值。
  • 太聪明了,太棒了!这有点模拟使用 java 中的两个索引取值,例如 [ i ] [ j ] 了解一切!
【解决方案2】:

这是您的代码,只做了最少的更改。您可以使用模从 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

【讨论】: