The function below will take a string(s) and rotate it a given amount(num). i.e cheer rotated by 7(cheer,7) will return jolly, and (melon, -10) will return cubed.

This is an attempt at exercise 8.10 from "How to think like a (Python) programmer, and it works just fine. The issue is I feel like there is a better way to write the ugly if..else statement, and possibly the whole function? Any pythonic suggestions??

Lanier

``````def rotate_word(s,num):
rotate = num % 26
newword = ' '
word=s.upper()
for letter in word:
if  ord(letter) + rotate > 90:
ascii_val = (ord(letter)  + rotate) - 26
else:
ascii_val = ord(letter) + rotate
newword = newword + chr(ascii_val)
return newword``````

Note the number of times you have "ord(letter) + rotate". A little algebra

``````## substituting ascii_val for ord(letter) + rotate
def rotate_word(s,num):
rotate = num % 26
newword = ' '
word=s.upper()
for letter in word:
if  ascii_val > 90:     ## ascii_val doesn't exist; this is just …``````

## All 2 Replies

Note the number of times you have "ord(letter) + rotate". A little algebra

``````## substituting ascii_val for ord(letter) + rotate
def rotate_word(s,num):
rotate = num % 26
newword = ' '
word=s.upper()
for letter in word:
if  ascii_val > 90:     ## ascii_val doesn't exist; this is just for demonstration
ascii_val = ascii_val - 26
else:
ascii_val = ascii_val
newword = newword + chr(ascii_val)
return newword

## stripped down it becomes
def rotate_word(s,num):
rotate = num % 26
newword = ' '
word=s.upper()
for letter in word:
ascii_val = ord(letter) + rotate
if  ascii_val > 90:
ascii_val -= 26
newword += chr(ascii_val)
return newword``````

One way to eliminate the "if" clause is like this:

chr(ord(c) - 65 + num) % 26 + 65

It subtracts the ord('A') to get the letter number (from 0...25), rotates the letter using %, and then adds the ord('A') back on.

Showcasing three favorite Pythonisms: anonymous functions, list generators, and the .join() method:

``````def rotate_word2(s, num):
s = s.upper()
rotate = lambda c, num: chr((ord(c) - 65 + num) % 26 + 65)
# same as 'def rotate(c,num): return char(ord(c) - 65 + num) % 26 + 65)'
new_letters = [rotate(x,num) for x in s]
return ''.join(new_letters)``````

And then, in the spirit of polymorphism, wouldn't it be nice if we could rotate whole phrases without clobbering case or punctuation?

``````def rotate_letter(c,num):
if c.isupper():
return chr((ord(c) - ord('A') + num) %26 + ord('A'))
elif c.islower():
return chr((ord(c) - ord('a') + num) %26 + ord('a'))
else:
return c

def rotate_phrase(s,num):
new_letters = [rotate_letter(x,num) for x in s]
return ''.join(new_letters)``````

Jeff

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts learning and sharing knowledge.