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??

Thanx in advance!

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 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 meeting, networking, learning, and sharing knowledge.