1

I'm working on decrypting a substitution cipher (not Caesar/ROT) with frequency analysis and no specialized tools. Let's say I wanted to use this cipher dictionary which seems good enough after analysis:

key = {
'S':'E',
'Q':'A',
'J':'T',
'U':'O',
'B':'I',
'N':'N',
'C':'L',
'G':'R',
'D':'H',
'V':'S',
'Z':'D',
'W':'C',
'M':'U',
'Y':'M',
'T':'F',
'X':'P',
'K':'G',
'E':'W',
'L':'Y',
'A':'B',
'F':'V',
'I':'K',
'O':'X',
'H':'J',
'R':'Q',
'P':'Z'
}

My code below has an obvious problem:

 with open(filename) as f:
     out = f.read()
     for k in key:
         out = out.replace(k,key[k])
     print out

Because it replaces every character one after the other, a character at a certain position gets replaced several times before the algorithm is done, instead of just once. (ie: first iteration the algorithm will replace all S with E, but then it reaches E in the dictionary and replaces all Es with W)

Does Python have a convenient way of doing this operation in one shot? Or will I be forced to keep track of the positions that have already been changed myself?

Juicy
  • 11,840
  • 35
  • 123
  • 212
  • Use [`str.translate`](https://docs.python.org/2/library/stdtypes.html#str.translate) – Ashwini Chaudhary Aug 02 '15 at 10:38
  • The file could be read and processed char by char. Answers at http://stackoverflow.com/questions/21915501/python-how-to-read-file-one-character-at-a-time show how to do that. –  Aug 02 '15 at 10:43

1 Answers1

3

For Python 3.x, You can use str.maketrans() (or string.maketrans() for Python 2.x) and str.translate() for this -

In [27]: key = {
   ....: 'S':'E',
   ....: 'Q':'A',
   ....: 'J':'T',
   ....: 'U':'O',
   ....: 'B':'I',
   ....: 'N':'N',
   ....: 'C':'L',
   ....: 'G':'R',
   ....: 'D':'H',
   ....: 'V':'S',
   ....: 'Z':'D',
   ....: 'W':'C',
   ....: 'M':'U',
   ....: 'Y':'M',
   ....: 'T':'F',
   ....: 'X':'P',
   ....: 'K':'G',
   ....: 'E':'W',
   ....: 'L':'Y',
   ....: 'A':'B',
   ....: 'F':'V',
   ....: 'I':'K',
   ....: 'O':'X',
   ....: 'H':'J',
   ....: 'R':'Q',
   ....: 'P':'Z'
   ....: }

In [28]: t = str.maketrans(key)

In [29]: "ABCDEFGZYXW".translate(t)
Out[29]: 'BILHWVRDMPC'

For Python 2.x,

>>> from string import maketrans
>>> t = maketrans(''.join(key.keys()) , ''.join(key.values()))
>>> "ABCDEFGZYXW".translate(t)
'BILHWVRDMPC'
Anand S Kumar
  • 88,551
  • 18
  • 188
  • 176