轮换列出字符串中的每个字母

时间:2019-05-15 03:01:04

标签: python python-3.x

我正在尝试制作一个Caesar密码来更改每个字母的密钥,目前我有一个工作密码可以对整个字符串进行一次加密,以1-25的速度运行,但是我希望每个字母都这样做。字符串“ ABC”会将A移1,B移2和C移3,从而产生BDF

我已经有一个有效的密码,只是不确定如何更改每个字母。

    upper = collections.deque(string.ascii_uppercase)
    lower = collections.deque(string.ascii_lowercase)

    upper.rotate(number_to_rotate_by)
    lower.rotate(number_to_rotate_by)

    upper = ''.join(list(upper))
    lower = ''.join(list(lower))

    return rotate_string.translate(str.maketrans(string.ascii_uppercase, upper)).translate(str.maketrans(string.ascii_lowercase, lower))
#print (caesar("This is simple", 2))
our_string = "ABC"


for i in range(len(string.ascii_uppercase)):
    print (i, "|", caesar(our_string, i))

结果是这样的:

0 | ABC
1 | ZAB
2 | YZA
3 | XYZ
4 | WXY
5 | VWX
6 | UVW
7 | TUV
8 | STU
9 | RST
10 | QRS
11 | PQR
12 | OPQ
13 | NOP
14 | MNO
15 | LMN
16 | KLM
17 | JKL
18 | IJK
19 | HIJ
20 | GHI
21 | FGH
22 | EFG
23 | DEF
24 | CDE
25 | BCD

我想要的是第一个字母偏移1或0,然后第二个偏移2,依此类推。

1 个答案:

答案 0 :(得分:1)

努力!请注意,映射不仅会重新排列字母表中的字母,因此永远不会通过旋转字母表来实现。在您的示例中,upper将变为以下映射:

ABCDEFGHIJKLMNOPQRSTUVWXYZ
BDFHJLNPRTVXZBDFHJLNPRTVXZ

还请注意,此密码不容易逆转,即不清楚是否要逆转'B'->'A'或'B'->'N'。

(旁注:如果我们将字母ZABCDEFGHIJKLMNOPQRSTUVWXY视为数字0-25,则此密码乘以2(以26为模):(x*2)%26。如果不是2,我们将乘以不能被2整除的任何数字,并且13,生成的密码将始终是可逆的。您知道原因吗?提示:[1][2]。)


当您对一段代码感到困惑时,通常这是一个好兆头,是时候将其一部分重构为单独的函数了,例如像这样:

(游乐场:https://ideone.com/wNSADR

import string


def letter_index(letter):
    """Determines the position of the given letter in the English alphabet

    'a' -> 0
    'A' -> 0
    'z' -> 25
    """
    if letter not in string.ascii_letters:
        raise ValueError("The argument must be an English letter")

    if letter in string.ascii_lowercase:
        return ord(letter) - ord('a')
    return ord(letter) - ord('A')


def caesar(s):
    """Ciphers the string s by shifting 'A'->'B', 'B'->'D', 'C'->'E', etc

    The shift is cyclic, i.e. 'A' comes after 'Z'.
    """
    ret = ""
    for letter in s:
        index = letter_index(letter)
        new_index = 2*index + 1
        if new_index >= len(string.ascii_lowercase):
            # The letter is shifted farther than 'Z'
            new_index %= len(string.ascii_lowercase)
        new_letter = chr(ord(letter) - index + new_index)
        ret += new_letter

    return ret


print('caesar("ABC"):', caesar("ABC"))
print('caesar("abc"):', caesar("abc"))
print('caesar("XYZ"):', caesar("XYZ"))

输出:

caesar("ABC"): BDF
caesar("abc"): bdf
caesar("XYZ"): VXZ

资源: