Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Text Shift function in Python

I'm writing code so you can shift text two places along the alphabet: 'ab cd' should become 'cd ef'. I'm using Python 2 and this is what I got so far:

def shifttext(shift):
    input=raw_input('Input text here: ')
    data = list(input)
    for i in data:
        data[i] = chr((ord(i) + shift) % 26)
        output = ''.join(data)
    return output
shifttext(3)

I get the following error:

File "level1.py", line 9, in <module>
    shifttext(3)
File "level1.py", line 5, in shifttext
    data[i] = chr((ord(i) + shift) % 26)
TypError: list indices must be integers, not str

So I have to change the letter to numbers somehow? But I thought I already did that?

like image 588
Ampi Severe Avatar asked Jan 20 '13 12:01

Ampi Severe


People also ask

How do you shift text in Python?

strs[(strs. index(i) + shift) % 26] : line above means find the index of the character i in strs and then add the shift value to it. Now, on the final value(index+shift) apply %26 to the get the shifted index. This shifted index when passed to strs[new_index] yields the desired shifted character.

How do you shift a string to the left in Python?

Approach is very simple, Separate string in two parts first & second, for Left rotation Lfirst = str[0 : d] and Lsecond = str[d :]. For Right rotation Rfirst = str[0 : len(str)-d] and Rsecond = str[len(str)-d : ].

How do you shift a value in Python?

To shift values in a list (replace the value at the first place of the list to its last place and vice versa), you need to rearrange the list with two slices. If a cyclic shift is necessary, repeat this command the required number of times in “for” cycle.

How do you increment a character in a string in Python?

To increment a character in a Python, we have to convert it into an integer and add 1 to it and then cast the resultant integer to char. We can achieve this using the builtin methods ord and chr.


5 Answers

You are looping over the list of characters, and i is thus a character. You then try to store that back into data using the i character as an index. That won't work.

Use enumerate() to get indexes and the values:

def shifttext(shift):
    input=raw_input('Input text here: ')
    data = list(input)
    for i, char in enumerate(data):
        data[i] = chr((ord(char) + shift) % 26)
    output = ''.join(data)
    return output

You can simplify this with a generator expression:

def shifttext(shift):
    input=raw_input('Input text here: ')
    return ''.join(chr((ord(char) + shift) % 26) for char in input)

But now you'll note that your % 26 won't work; the ASCII codepoints start after 26:

>>> ord('a')
97

You'll need to use the ord('a') value to be able to use a modulus instead; subtracting puts your values in the range 0-25, and you add it again afterwards:

    a = ord('a')
    return ''.join(chr((ord(char) - a + shift) % 26) + a) for char in input)

but that will only work for lower-case letters; which might be fine, but you can force that by lowercasing the input:

    a = ord('a')
    return ''.join(chr((ord(char) - a + shift) % 26 + a) for char in input.lower())

If we then move asking for the input out of the function to focus it on doing one job well, this becomes:

def shifttext(text, shift):
    a = ord('a')
    return ''.join(chr((ord(char) - a + shift) % 26 + a) for char in text.lower())

print shifttext(raw_input('Input text here: '), 3)

and using this on the interactive prompt I see:

>>> print shifttext(raw_input('Input text here: '), 3)
Input text here: Cesarsalad!
fhvduvdodgr

Of course, now punctuation is taken along. Last revision, now only shifting letters:

def shifttext(text, shift):
    a = ord('a')
    return ''.join(
        chr((ord(char) - a + shift) % 26 + a) if 'a' <= char <= 'z' else char
        for char in text.lower())

and we get:

>>> print shifttext(raw_input('Input text here: '), 3)
Input text here: Ceasarsalad!
fhdvduvdodg!
like image 73
Martijn Pieters Avatar answered Oct 07 '22 15:10

Martijn Pieters


Looks you're doing cesar-cipher encryption, so you can try something like this:

strs = 'abcdefghijklmnopqrstuvwxyz'      #use a string like this, instead of ord() 
def shifttext(shift):
    inp = raw_input('Input text here: ')
    data = []
    for i in inp:                     #iterate over the text not some list
        if i.strip() and i in strs:                 # if the char is not a space ""  
            data.append(strs[(strs.index(i) + shift) % 26])    
        else:
            data.append(i)           #if space the simply append it to data
    output = ''.join(data)
    return output

output:

In [2]: shifttext(3)
Input text here: how are you?
Out[2]: 'krz duh brx?'

In [3]: shifttext(3)
Input text here: Fine.
Out[3]: 'Flqh.'

strs[(strs.index(i) + shift) % 26]: line above means find the index of the character i in strs and then add the shift value to it.Now, on the final value(index+shift) apply %26 to the get the shifted index. This shifted index when passed to strs[new_index] yields the desired shifted character.

like image 22
Ashwini Chaudhary Avatar answered Oct 07 '22 15:10

Ashwini Chaudhary


Martijn's answer is great. Here is another way to achieve the same thing:

import string

def shifttext(text, shift):
    shift %= 26 # optional, allows for |shift| > 26 
    alphabet = string.lowercase # 'abcdefghijklmnopqrstuvwxyz' (note: for Python 3, use string.ascii_lowercase instead)
    shifted_alphabet = alphabet[shift:] + alphabet[:shift]
    return string.translate(text, string.maketrans(alphabet, shifted_alphabet))

print shifttext(raw_input('Input text here: '), 3)
like image 25
oli Avatar answered Oct 07 '22 15:10

oli


It's easier to write a straight function shifttext(text, shift). If you want a prompt, use Python's interactive mode python -i shift.py

> shifttext('hello', 2)
'jgnnq'
like image 1
Colonel Panic Avatar answered Oct 07 '22 14:10

Colonel Panic


Tried with Basic python. may useful for someone.

# Caesar cipher
import sys

text = input("Enter your message: ")

cipher = ''
try:
  number = int(input("Enter Number to shift the value : "))
except ValueError:
  print("Entered number should be integer. please re0enter the value")
  try:
    number = int(input("Enter Number to shift the value : "))
  except:
    print("Error occurred. please try again.")
    sys.exit(2)
  
for char in text:
    if not char.isalpha():
      flag = char
    elif char.isupper():
      code = ord(char) + number
      if 64 < code <= 90:
        flag = chr(code)
      elif code > 90:
        flag = chr((code - 90) + 64)
        
    elif char.islower():
      code = ord(char) + number
      if 96 < code <= 122:
        flag = chr(code)
      elif code > 122:
        flag = chr((code - 122) + 96)
    
    else:
      print("not supported value by ASCII")
    
    cipher += flag

print(cipher)
like image 1
Venkatesha K Avatar answered Oct 07 '22 16:10

Venkatesha K