0

I am very new to Python and have run into a road block. Is it possible to use list comprehension to perform a shift on each letter of a word in a list? Also how could I utilize ord() and chr() in a similar list comprehension manner?

So far I have the following code:

def shift( file1="file1.txt",  file2 ="file2.txt"):

    key = int(input("Enter shift key: ")) 

    with open(" file1. txt") as readfile:

             lines = readfile.readlines()

             lines = [words.lower() for words in lines] 

             lines = [ words.split(" ")  for words in lines] 

All I need now is to perform the actual shift but I am stumped :/

3 Answers3

0

You can use str.join , iterating over each ch/character in each word from the word_list, you can use whatever formula you have to create your cipher.

word_list = ["Foo","Bar","Foobar"]
print(["".join(chr(ord(ch) + 10) for ch in word.lower()) for word in word_list ])

['pyy', 'lk|', 'pyylk|']
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
0

Here is a simple Caesar Shift using a comprehension:

>>> string = 'CaesarShift'; shift=3
>>> ''.join(chr(ord('a') + (ord(c)-ord('a')+shift) % 26) for c in string)
'zdhvdupkliw'

This illustrates the concept but makes no attempt to handle spaces or punctuation.

Reversibility

>>> new = ''.join(chr(ord('a') + (ord(c)-ord('a')+shift) % 26) for c in string.lower())
>>> ''.join(chr(ord('a') + (ord(c)-ord('a')-shift) % 26) for c in new)
'caesarshift'
John1024
  • 109,961
  • 14
  • 137
  • 171
0
  1. Wrap Around: The Caesar Shift is a wrap-around shift cipher, so you have to have an algorithm to wrap around strings.

    If you consider letters as numbers, then you could write the letters out as [0, 1 ... 25], i.e. range(26).

    If you do a Caesar shift of 10 on this, you will get: [10, 11 ... 25, 26 ... 35].

    Character 26 isn't in the alphabet. You will need to change this to 0. Then change character 27 to 1, and so on. So, the transformation you are looking for, (if the alphabet was arranged from 0 to 25) is, mod( letterValue + 10, 26).

  2. However, the letters do not start from 0, so you will have to first subtract the value of ord('a') and then add it later.

    The letterValue in the above expression is simply: ord(ch) - ord('a'). So change the earlier expression to (chr(ch) - ord('a') + 10) % 26.

    Then change it back using: chr((chr(ch) - ord('a') + 10) % 26 + ord('a')).

    Since ord('a') is 96, you can speed up this process a little by using: chr((chr(ch) - 96 + 10)%26 + 96), i.e., chr((chr(ch)-86)%26 + 96)

  3. Non alphabetic characters: What will characters such as ? and ! translate to? These generally go through unaltered. You can supply that with an if condition and check if the requested character is in string.ascii_lowercase.

    Something like:

    from string import ascii_lowercase as lowerLetters
    
    def toCaesar(ch):
    
        if ch in lowerLetters: 
            return chr((chr(ch) - 86)%26 + 96)
        else:
            return ch
    

The rest I think you already have.

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
ssm
  • 5,277
  • 1
  • 24
  • 42