Looping for every character in a string in Python decoder ring
-
08-03-2021 - |
Question
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.
Solution
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.
OTHER TIPS
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'
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
I would recommend making the decoder ring a dictionary. Then open the input file for reading, read the file, loop through a character at a time and use the dictionary to translate to an output string. Finally write that string to a file.