Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looping for every character in a string in Python decoder ring

I'm trying to make a simple decoder ring in Python.

Example:

a=b, `b=c, c=d, etc.  

I want the script to take an encoded message and output the decoded message.
For instance, I would input "ifmmp" and it would output "hello".

I've been thinking I need to split all the characters up and loop through them and change their chr() or ord() values.

There doesn't seem to be any documentation for this in python.

like image 384
user1063543 Avatar asked Nov 24 '11 09:11

user1063543


3 Answers

How about:

s = 'ifmmp'
new_s = ''
for c in s:
    n = ord(c)
    n = n - 1
    if n < ord('a'):
        # 'a' -> 'z'
        n = ord('z')
    new_s += chr(n)
# print('new_s = %r' % new_s)  -> new_s = 'hello'

Of course, this is only handling small letters, not capital.

like image 142
Some programmer dude Avatar answered Oct 11 '22 11:10

Some programmer dude


Forget loops, whenever possible use the features built in to Python:

from string import maketrans, translate, ascii_lowercase
import functools
translation = maketrans(ascii_lowercase, ascii_lowercase[-1]+ascii_lowercase[:-1])
decipher = functools.partial(string.translate, table=translation)

print(decipher("ifmmp")) # 'hello'
like image 20
Duncan Avatar answered Oct 11 '22 11:10

Duncan


from string import maketrans

table = maketrans('abcdefghijklmnopqrstuvwxyz/','zabcdefghijklmnopqrstuvwxy ')

for x in ('pdfbo','qipophsbqi','cmvf/nppo/jo/b/sfe/tlz'):
    print x,' -> ',x.translate(table)

result

pdfbo  ->  ocean
qipophsbqi  ->  phonograph
cmvf/nppo/jo/b/sfe/tlz  ->  blue moon in a red sky

.

Edit

I rewrote the algorithm of Joachim (function better()) and I wrote my own solution not using maketrans() ( yop() ) :

s = '{ifmmp}\t\tcmvf-nppo \n SUNNY ~ ajhabh 14568'

def bof(s):
    new_s = ''
    for c in s:
        n = ord(c)
        n = n - 1
        if n < ord('a'):
            # 'a' -> 'z'
            n = ord('z')
        new_s += chr(n)
    return new_s


def better(s):
    li = []
    for c in s:
        n = ord(c)-1
        if n == 96:
            li.append('z')
        elif 96<n<122:
            li.append(chr(n))
        else:
            li.append(c)
    return ''.join(li)

def yop(s):
    gen = ((c,ord(c)-1) for c in s)
    return ''.join('z' if y==96 else chr(y) if 96<y<122 else x for x,y in gen)


def better_yop(s):
    def gen(h):
        for c in h:
            n = ord(c)-1
            if n == 96:
                yield 'z'
            elif 96<n<122:
                yield chr(n)
            else:
                yield c
    return ''.join(gen(s))

for truc in (s,bof(s),better(s),yop(s),better_yop(s)):
    print '%r\n%s\n' % (truc,truc)

result

'{ifmmp}\t\tcmvf-nppo \n SUNNY ~ ajhabh 14568'
{ifmmp}     cmvf-nppo 
 SUNNY ~ ajhabh 14568

'zhello|zzbluezmoonzzzzzzzzz}zzigzagzzzzzz'
zhello|zzbluezmoonzzzzzzzzz}zzigzagzzzzzz

'{hello}\t\tblue-moon \n SUNNY ~ zigzag 14568'
{hello}     blue-moon 
 SUNNY ~ zigzag 14568

'{hello}\t\tblue-moon \n SUNNY ~ zigzag 14568'
{hello}     blue-moon 
 SUNNY ~ zigzag 14568

'{hello}\t\tblue-moon \n SUNNY ~ zigzag 14568'
{hello}     blue-moon 
 SUNNY ~ zigzag 14568

However , my function yop() is slower than the function better()

.

Edit

Now the function better_yop() has a speed equivalent to the speed of better()
However, better() seems to be slightly faster than better_yop(). Since it is also simpler, better() is the best

like image 33
eyquem Avatar answered Oct 11 '22 10:10

eyquem