【问题标题】:Python Function that receives a letter and rotates that letter 13 places to the right接收一个字母并将该字母向右旋转 13 位的 Python 函数
【发布时间】:2019-02-05 13:54:12
【问题描述】:

我正在尝试创建一个使用凯撒密码加密消息的 Python 函数。

到目前为止,我的代码是

letter = input("Enter a letter: ")
def alphabet_position(letter):
alphabet_pos = {'A':0, 'a':0, 'B':1, 'b':1, 'C':2, 'c':2, 'D':3,
                'd':3, 'E':4, 'e':4, 'F':5, 'f':5, 'G':6, 'g':6,
                'H':7, 'h':7, 'I':8, 'i':8, 'J':9, 'j':9, 'K':10,
                'k':10, 'L':11, 'l':11, 'M':12, 'm':12, 'N': 13,
                'n':13, 'O':14, 'o':14, 'P':15, 'p':15, 'Q':16,
                'q':16, 'R':17, 'r':17, 'S':18, 's':18, 'T':19,
                't':19, 'U':20, 'u':20, 'V':21, 'v':21, 'W':22,
                'w':22, 'X':23, 'x':23, 'Y':24, 'y':24, 'Z':25, 'z':25 }
pos = alphabet_pos[letter]
return pos  

当我尝试运行我的代码时,它会询问该字母,但之后它不会返回任何内容

如果您有任何建议,请提供帮助。

【问题讨论】:

标签: python string input


【解决方案1】:

您可以使用 ordchr 函数的快速计算来代替:

def encrypt(letter):
    return chr((ord(letter.lower()) - ord('a') + 13) % 26 + ord('a'))

这样:

print(encrypt('a'))
print(encrypt('o'))

输出:

n
b

【讨论】:

    【解决方案2】:

    您需要以不同的方式访问您的字典:

    pos = alphabet_pos.get(letter)
    return pos
    

    然后你终于可以调用函数了。

    alphabet_position(letter)
    

    【讨论】:

      【解决方案3】:

      您可以定义两个字典,一个与另一个相反。您需要注意几个方面:

      • 大小写是否重要。如果不是,请使用str.casefold,如下所示。
      • 当您从字母表的末尾滚动时会发生什么,例如第 13 个字母“z”之后。下面我们假设您从头开始。
      • 不要手动输入字母表。您可以使用string 模块。

      这是一个演示:

      letter = input("Enter a letter: ")
      
      from string import ascii_lowercase
      
      def get_next(letter, n):
          pos_alpha = dict(enumerate(ascii_lowercase))
          alpha_pos = {v: k for k, v in pos_alpha.items()}
          return pos_alpha[alpha_pos[letter.casefold()] + n % 26]
      
      get_next(letter, 13)
      
      Enter a letter: a
      'n'
      

      【讨论】:

        【解决方案4】:

        如果你需要一个全新的编码字典

        import string
        import numpy as np, random
        letters = string.ascii_uppercase
        d=dict(zip(list(letters),range(0,len(letters))))
        encoded_dic={}
        
        def get_caesar_value(v, by=13):
            return(v+by)%26
        
        for k,v in d.items():
            encoded_dic[k]=chr(65+get_caesar_value(v))
        print(encoded_dic)
        

        输出:

        {'A': 'N', 'C': 'P', 'B': 'O', 'E': 'R', 'D': 'Q', 'G': 'T', 'F': 'S', 'I': 'V', 'H': 'U', 'K': 'X', 'J': 'W', 'M': 'Z', 'L': 'Y', 'O': 'B', 'N': 'A', 'Q': 'D', 'P': 'C', 'S': 'F', 'R': 'E', 'U': 'H', 'T': 'G', 'W': 'J', 'V': 'I', 'Y': 'L', 'X': 'K', 'Z': 'M'}
        

        【讨论】:

          【解决方案5】:

          您拥有的代码仅将字母映射到一个位置。我们将重写它并创建一个rotate 函数。

          代码

          import string
          import itertools as it
          
          
          LOOKUP = {
              **{x:i for i, x in enumerate(string.ascii_lowercase)},
              **{x:i for i, x in enumerate(string.ascii_uppercase)}
          }
          
          
          def abc_position(letter):
              """Return the alpha position of a letter."""
              return LOOKUP[letter]
          

          def rotate(letter, shift=13):
              """Return a letter shifted some positions to the right; recycle at the end."""
              iterable = it.cycle(string.ascii_lowercase)
              start = it.dropwhile(lambda x: x != letter.casefold(), iterable)
          
              # Advance the iterator
              for i, x in zip(range(shift+1), start):
                  res = x
              if letter.isupper():
                  return res.upper()
              return res
          

          测试

          func = abc_position
          assert func("a") == 0
          assert func("A") == 0
          assert func("c") == 2
          assert func("z") == 25
          
          func = rotate
          assert func("h") == "u"
          assert func("a", 0) == "a"
          assert func("A", 0) == "A"
          assert func("a", 2) == "c"
          assert func("c", 3) == "f"
          assert func("A", 2) == "C"
          assert func("a", 26) == "a"
          # Restart after "z"
          assert func("z", 1) == "a"
          assert func("Z", 1) == "A"
          

          演示

          >>> letter = input("Enter a letter: ")
          Enter a letter: h
          >>> rot = rotate(letter, 13)
          >>> rot
          'u'
          >>> abc_position(rot)
          20
          

          这里我们将字母"h"旋转了13个位置,得到一个字母,然后确定这个结果字母在abc's的普通字符串中的位置。


          详情

          abc_position()

          重写了这个函数来查找一个字母的位置。它合并了两个字典:

          1. 枚举小写 ascii 字母的方法
          2. 枚举大写 ascii 字母的方法

          string 模块已经有了这个字母。

          rotate()

          这个函数只旋转小写字母;大写字母从小写位置转换而来。通过创建一个无限的小写字母cycle(迭代器)来旋转字母字符串。

          1. 循环首先前进到所需字母处的start。这是通过删除所有看起来不像传入的字母来完成的。
          2. 然后它在循环中被推进一些等于shift 的次数。循环只是消耗或向前移动迭代器的一种方式。我们只关心最后一个字母,而不是中间的那些。返回此字母,小写或大写。

          由于返回的是字母(不是位置),您现在可以使用 abc_position() 函数找到它的正常位置。

          替代品

          其他旋转函数可以替代rotate()

          import codecs
          
          
          def rot13(letter):
              return codecs.encode(letter, "rot13")
          

          def rot13(letter):
              table = str.maketrans( 
                  "ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz", 
                  "NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm")
              return str.translate(letter, table)
          

          但是,这些选项仅限于 rot13,而 rotate() 可以移动任意数字。注意:rot26 会循环回到开头,例如rotate("a", 26) -> a.

          另请参阅this post,了解如何制作真正的 rot13 密码。

          另请参阅 itertools.cycleitertools.dropwhile 上的文档。

          【讨论】:

            猜你喜欢
            • 2017-04-21
            • 2022-12-30
            • 2014-05-26
            • 1970-01-01
            • 1970-01-01
            • 2013-11-15
            • 1970-01-01
            • 2017-10-26
            • 1970-01-01
            相关资源
            最近更新 更多