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.
{"ft_lang_label":"__label__en","ft_lang_prob":0.7420163,"math_prob":0.98166615,"size":689,"snap":"2021-43-2021-49","text_gpt3_token_len":192,"char_repetition_ratio":0.1270073,"word_repetition_ratio":0.0,"special_character_ratio":0.28592163,"punctuation_ratio":0.15384616,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9707481,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2021-10-28T20:22:14Z\",\"WARC-Record-ID\":\"<urn:uuid:b69b8d56-2d53-433f-b9a0-4d807ae32073>\",\"Content-Length\":\"65567\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:f56325f2-f40c-462b-92d2-60a2233303f0>\",\"WARC-Concurrent-To\":\"<urn:uuid:ded819bb-44d7-42a7-974c-ccfb450f7158>\",\"WARC-IP-Address\":\"172.66.42.251\",\"WARC-Target-URI\":\"https://www.daniweb.com/programming/software-development/threads/113561/can-i-make-def-rotate-word-s-num-more-pythonic\",\"WARC-Payload-Digest\":\"sha1:U2H5HLPOIEUUUAPUBVA2NAPSDWQZVW6V\",\"WARC-Block-Digest\":\"sha1:XUACOXPYHRMXKSGIHM3BSAHYGNY4NJKW\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2021/CC-MAIN-2021-43/CC-MAIN-2021-43_segments_1634323588526.57_warc_CC-MAIN-20211028193601-20211028223601-00453.warc.gz\"}"}