novice2020
novice2020

Reputation: 115

Printing alphabets advanced by n in Python

how can i write a python program to intake some alphabets in and print out (alphabets+n) in the output. Example

my_string = 'abc'
expected_output = 'cde' # n=2

One way I've thought is by using str.maketrans, and mapping the original input to (alphabets + n). Is there any other way?

PS: xyz should translate to abc

I've tried to write my own code as well for this, (apart from the infinitely better answers mentioned):

number = 2
prim =  """abc! fgdf """
final = prim.lower()
for x in final:
    if(x =="y"):
        print("a", end="")
    elif(x=="z"):
        print("b", end="")
    else:
        conv = ord(x)
        x = conv+number
        print(chr(x),end="")

Any comments on how to not convert special chars? thanks

Upvotes: 0

Views: 665

Answers (4)

bluepeach
bluepeach

Reputation: 17

test_data = (('abz', 2), ('abc', 3), ('aek', 26), ('abcd', 25))
# translate every character
def shiftstr(s, k):
    if not (isinstance(s, str) and isinstance(k, int) and k >=0):
        return s
    a = ord('a')
    return ''.join([chr(a+((ord(c)-a+k)%26)) for c in s])

for s, k in test_data:
    print(shiftstr(s, k))
print('----')

# translate at most 26 characters, rest look up dictionary at O(1)
def shiftstr(s, k):
    if not (isinstance(s, str) and isinstance(k, int) and k >=0):
        return s
    a = ord('a')
    d = {}
    l = []
    for c in s:
        v = d.get(c)
        if v is None:
            v = chr(a+((ord(c)-a+k)%26))
            d[c] = v
        l.append(v)
    return ''.join(l)

for s, k in test_data:
    print(shiftstr(s, k))
 Testing shiftstr_test.py (above code):
 $ python3 shiftstr_test.py 
 cdb
 def
 aek
 zabc
----
cdb
def
aek
zabc

It covers wrapping.

Upvotes: 0

novice2020
novice2020

Reputation: 115

I've made the following change to the code:

number = 2
prim =  """Special() ops() chars!!"""
final = prim.lower()
for x in final:
    if(x =="y"):
        print("a", end="")
    elif(x=="z"):
        print("b", end="")
    elif (ord(x) in range(97, 124)):
        conv = ord(x)
        x = conv+number
        print(chr(x),end="")
    else:
        print(x, end="")

**Output**: urgekcn() qru() ejctu!!

Upvotes: 0

L3viathan
L3viathan

Reputation: 27273

If you don't care about wrapping around, you can just do:

def shiftString(string, number):
    return "".join(map(lambda x: chr(ord(x)+number),string))

If you do want to wrap around (think Caesar chiffre), you'll need to specify a start and an end of where the alphabet begins and ends:

def shiftString(string, number, start=97, num_of_symbols=26):
    return "".join(map(lambda x: chr(((ord(x)+number-start) %
           num_of_symbols)+start) if start <= ord(x) <= start+num_of_symbols
           else x,string))

That would, e.g., convert abcxyz, when given a shift of 2, into cdezab.

If you actually want to use it for "encryption", make sure to exclude non-alphabetic characters (like spaces etc.) from it.

edit: Shameless plug of my Vignère tool in Python

edit2: Now only converts in its range.

Upvotes: 2

nu11p01n73R
nu11p01n73R

Reputation: 26667

How about something like

>>> my_string = "abc"
>>> n = 2
>>> "".join([ chr(ord(i) + n) for i in my_string])
'cde'

Note As mentioned in comments the question is bit vague about what to do when the edge cases are encoundered like xyz


Edit To take care of edge cases, you can write something like

>>> from string import ascii_lowercase
>>> lower = ascii_lowercase
>>> input = "xyz"
>>> "".join([ lower[(lower.index(i)+2)%26] for i in input ])
'zab'
>>> input = "abc"
>>> "".join([ lower[(lower.index(i)+2)%26] for i in input ])
'cde'

Upvotes: 2

Related Questions