Reputation: 43
I'm trying to make a program which takes a word or sentence, and then shifts each character one place in the alphabet. This is my minimal reproducible example:
alphabet = []
alphabet = [chr(x) for x in range(ord('a'), ord('z') +1)]
word = 'hello'
new_word = [ ]
for char in word:
if char in alphabet:
new_pos = alphabet.index(char) + 1
if new_pos > len(alphabet):
new_pos %= len(alphabet)
new_word.append(alphabet[new_pos])
else:
continue
my question is: why doesn't this shift the characters of the word one place in the alphabet?
Upvotes: 2
Views: 144
Reputation: 41872
The str
methods maketrans
and translate
are perfect for this type of problem:
from string import ascii_lowercase as alphabet
# One time initialization:
translation = str.maketrans(alphabet, alphabet[1:] + alphabet[:1])
# Can be reused multiple times:
words = ('hello', 'add', 'inks ohm', 'end')
for word in words:
new_word = word.translate(translation)
print(word, '->', new_word)
OUTPUT
% python3 test.py
hello -> ifmmp
add -> bee
inks ohm -> jolt pin
end -> foe
%
a program which takes a word or sentence
Your original code, nor the currently accepted code, handle a sentence as they squeeze out the spaces. The code above will handle sentences correctly, passing through things that aren't letters.
Here's a rework of your code to handle sentences correctly:
from string import ascii_lowercase as alphabet
phrase = 'inks ohm'
new_phrase = ''
for character in phrase:
if character in alphabet:
new_position = (alphabet.index(character) + 1) % len(alphabet)
character = alphabet[new_position]
new_phrase += character
print(new_phrase)
Of course, these all only handle lower case and to handle sentences properly, you need to extend them to handle upper case as well. An exercise left to the reader.
Upvotes: 1
Reputation: 27557
You can instead use this list comprehension:
word = 'hello'
new_word = ''.join([chr(ord(w)+1) if w.lower()!='z' else chr(ord(w)-25) for w in word])
print(new_word)
Output:
ifmmp
You can also:
new_word = ''.join([chr(ord(w)+1) if w not in ['z','Z'] else chr(ord(w)-25) for w in word])
Upvotes: 3
Reputation: 984
I got it to work by making new_word
a string, and doing string concatenation (instead of array appending).
alphabet = []
alphabet = [chr(x) for x in range(ord('a'), ord('z') +1)]
word = 'hello'
new_word = ''
for char in word:
if char in alphabet:
new_pos = alphabet.index(char) + 1
if new_pos >= len(alphabet):
new_pos %= len(alphabet)
new_word = new_word + alphabet[new_pos]
else:
continue
print(word, new_word)
Prints:
hello ifmmp
Upvotes: 2
Reputation: 21956
In Python, it’s often best to strive for compact solutions that use the expressive power of the language instead of extra loops and temporary data structures. Fewer lines of code = fewer places for things to go wrong.
The answer from Ann Zen is a good example of a pythonic approach. I’ll generalize that solution a little to deal with (1) possible future changes to your alphabet and (2) handling input characters not in your alphabet.
alpha_min, alpha_max = sorted(['a', 'z'])
alpha_count = ord(alpha_max) - ord(alpha_min) + 1
phrase = 'hello there 123'
new_phrase = ''.join([chr(((ord(w)+1-alpha_min) % alpha_count) + alpha_min) for w in phrase])
print(new_phrase)
Outputs ifmmp uifsf 123
.
Upvotes: 0
Reputation: 122
Good question Jordhi!
Letters can not be incremented by 1 but their ASCII code can be. ASCII codes are numerical representations of characters, each character on the keyboard has a unique ASCII code.
So first the character is converted into it's ASCII code by using the inbuilt python function ord() and stored into the integer variable num. Num is then incremented by 1 to get the ASCII code of the next letter. Then the ASCII code is converted back into a character using the function chr()
So the code:
word = 'hello'
new_word = ''
for char in word:
if char.isalpha():
num=ord(char)
num=num+1
x=chr(num)
new_word+=x
print(word, new_word)
Will give you the output you're looking for:
hello ifmmp
Upvotes: 0