3

I'm trying to create a function

rotate_character(char, rot)

that receives a character, "char" (a string with a length of 1), and an integer "rot". The function should return a new string with a length of 1, which is the result of rotating char by rot number of places to the right.

So an input of "A" for char and "13" for rot would return

N

(with A having an initial value of 0, and B having an initial value of 1, etc). Capitalization should be maintained during rotation.

I already created a function that returns the position of a letter in the alphabet by using a dictionary:

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  

I figure that I can use this function to get the initial value of (char) before rotation.

def rotate_character(char, rot)
    initial_char = alphabet_position(char)
    final_char = initial_char + rot

But my problem is that, if initial_char + rot is greater than 25, I need to wrap back to the beginning of the alphabet and continue counting. So an input of "w" (initial value of 22) + an input of 8 for rot should return

e

How do I say this using python?

if final_char > 25, start at the beginning of the list and continue counting

And do I necessarily need to use the dictionary that I created in the alphabet_position function? It was also suggested that I find the character number by using Python's built-in list of letters, like this:

import string

letter = input('enter a letter: ')

def alphabet_position(letter):
    letter = letter.lower()
    return list(string.ascii_lowercase).index(letter)

return(alphabet_position(letter))

I'm not sure which one of these is the better option to go with when you have to wrap while you're counting. Thanks for your help / suggestions!

EDIT:

Now my code looks like this:

letter = input("enter a letter")
rotate = input("enter a number")

def rotate(letter, rotate):
    letter = letter.lower()
    return chr((ord(letter) + rotate - 97) % 26 + 97)

print(rotate(letter))

EDIT 2:

def rotate(letter, number):
    letter = letter.lower()
    shift = 97 if letter.islower() else 65
    return chr((ord(letter) + number - shift) % 26 + shift)

letter = input('Enter a letter: ')
number = int(eval(input('Enter a number: ')
print(rotate(letter, number))

gave me a ParseError: "ParseError: bad input on line 8" (the print line)

Community
  • 1
  • 1
HappyHands31
  • 4,001
  • 17
  • 59
  • 109
  • 1
    Concerning the error from your second edit: In the line before the `print` the number of parentheses is unbalanced. By the way: [**Stop using `eval`!**](http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html) Just `number = int(input('Enter a number: '))` is enough. – Matthias Dec 07 '16 at 07:44

2 Answers2

4
def rotate(letter, rot):
    shift = 97 if letter.islower() else 65
    return chr((ord(letter) + rot - shift) % 26 + shift)

letter = input('Enter a letter: ')
rot = int(input('Enter a number: '))
print(rotate(letter, rot))
Thmei Esi
  • 434
  • 2
  • 9
  • So does that mean I need to get rid of my first function, alphabet_position? Please see the edit above to see exactly what I using now. I tried to run it and got a TypeError: "TypeError: rotate() takes exactly 2 arguments (1 given) on line 8". Also I need to maintain capitalization i.e. if I enter A + 13 it should return N instead of n. – HappyHands31 Dec 07 '16 at 03:56
  • Yes, that function is unnecessary. The `ord(letter) + rotate - 97` does the same thing and rotates. Then the `% 26 + 97` makes sure that the `chr` function will be happy. Best of all, this solution does not require anything more than built in functions. No need for imports. – Thmei Esi Dec 07 '16 at 04:00
  • Okay, do you have any idea why I'm getting the error message then? "TypeError: rotate() takes exactly 2 arguments (1 given) on line 8" See my edit above for what I'm using. – HappyHands31 Dec 07 '16 at 04:04
  • I have changed my answer to match your code. The type error occured because `rotate` needs to be given two values `letter` and `rotate`, but in your code you only give it one `rotate(letter)` should be `rotate(letter, rot)` – Thmei Esi Dec 07 '16 at 04:11
  • Yes. See my revised answer for how to resolve that name conflict. I simply call the input `rot` instead of `rotate` – Thmei Esi Dec 07 '16 at 04:14
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/129956/discussion-between-thmei-esi-and-happyhands31). – Thmei Esi Dec 07 '16 at 04:17
2

You can use the string module and then use the modulo operator to "wrap around" the end of the alphabet:

from string import lowercase

def rotate_char(char, rot):

    i = lowercase.index(char)
    return lowercase[(i + rot) % 25]
kiliantics
  • 1,148
  • 1
  • 8
  • 11