By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,715 Members | 748 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,715 IT Pros & Developers. It's quick & easy.

Cipher/decipher program

P: 2
I'm trying to make a simple program that will convert to and from a cipher that's already set.

Expand|Select|Wrap|Line Numbers
  1. foo = 'a = hz\nb = ye\nc = uo\nd = pd\ne = qi\nf = jy\ng = ru\nh = sw\ni = ln\nj = ae\nk = na\nl = rt\nm = wu\nn = is\no = nd\np = hw\nq = op\nr = kb\ns = vf\nt = fc\nu = xr\nv = ex\nw = mn\nx = gb\ny = bu\nz = ie\n. =  *right wing slash* \n, =  *hand wave* \n" =  *hand curve* \n! =  *double hand jerk* \n? =  *wing wave* \n... =  *squiggly hand motion* '
  2. repl={}
  3. reverse_repl={}
  4. import sys
  5. #Generate replacement tables
  6. for str in foo.split("\n"):
  7.     parts=str.split(" = ")
  8.     repl[parts[0]]=parts[1]
  9.     repl[parts[0].lower()]=parts[1]
  10.     reverse_repl[parts[1]]=parts[0]
  11. def encipher():
  12.     outstr = ''
  13.     instr = sys.stdin.readline()
  14.     i = 0
  15.     for i in range(len(instr)):
  16.         c = instr[i]
  17.         if (instr[i:i+3]=='...'):
  18.             outstr+=repl['...']
  19.             i+=3
  20.         else:
  21.             if (c in repl):
  22.                 outstr+=repl[c]
  23.                 i+=1
  24.             else:
  25.                 outstr+=c
  26.                 i+=1
  27.     print outstr
  28. def decipher():
  29.     outstr = ''
  30.     instr = sys.stdin.readline()
  31.     instr=instr[:-1]
  32.     i = 0
  33.     c = instr[i]
  34.     while (i<len(instr)):
  35.             if (instr[i:i+2]):
  36.                 outstr+=reverse_repl[instr[i:i+2]]
  37.                 i+=2
  38.             else:
  39.                 outstr+=c
  40.                 i+=1
  41.     print outstr
  42. if (sys.argv[1]=="-e"):
  43.     encipher()
  44. else:
  45.     decipher()
  46. raw_input('press Return to end program>')
Couple of things I couldn't get working:
  1. I couldn't separate the '...' from the '.' The '...' will give the correct equivalent from the list when enciphering, but will also follow it with 2 instances of '.'
  2. For deciphering, it works up until it goes up against a character that's not in "foo" like 123 or a space.

Thanks for your help in advance.
Dec 14 '08 #1
Share this Question
Share on Google+
4 Replies


bvdet
Expert Mod 2.5K+
P: 2,851
It appears that you want to replace each character with a unique 2 character string with a special exception for "...". I don't understand what *squiggly hand motion* is, but I'll assume that it is 2 characters. If a character is not in repl, double it so we be consistent.

Your code:
Expand|Select|Wrap|Line Numbers
  1.     for i in range(len(instr)):
  2.         c = instr[i]
  3.         if (instr[i:i+3]=='...'):
  4.             outstr+=repl['...']
  5.             i+=3
  6.         else:
  7.             if (c in repl):
  8.                 outstr+=repl[c]
  9.                 i+=1
  10.             else:
  11.                 outstr+=c
  12.                 i+=1
Variable i is updated each iteration. If you assign i in the body of the loop, you will lose the assignment.
Try the following instead:
Expand|Select|Wrap|Line Numbers
  1.     while i < len(instr):
  2.         c = instr[i]
  3.         if instr[i:i+3] == '...':
  4.             outstr += repl['...']
  5.             i+=3
  6.         elif c in repl:
  7.             outstr += repl[c]
  8.             i+=1
  9.         else:
  10.             outstr += c*2
  11.             i+=1


To get the code to work, I replaced your code:
Expand|Select|Wrap|Line Numbers
  1.     while (i<len(instr)):
  2.             if (instr[i:i+2]):
  3.                 outstr+=reverse_repl[instr[i:i+2]]
  4.                 i+=2
  5.             else:
  6.                 outstr+=c
  7.                 i+=1
with the following code:
Expand|Select|Wrap|Line Numbers
  1.     while i<len(instr):
  2.         if reverse_repl.has_key(instr[i:i+2]):
  3.             outstr += reverse_repl[instr[i:i+2]]
  4.         else:
  5.             outstr += instr[i][0]
  6.         i+=2
There were several places in your code where parentheses were not required. Avoid using str as a variable name, because the built-in function str() will be masked.
HTH --BV
Dec 14 '08 #2

P: 2
Thanks for the quick reply. I actually worked a bit on my code while I waited so my code looks pretty similar to yours. My code looks like this right now:

Expand|Select|Wrap|Line Numbers
  1. foo = 'a = hz\nb = ye\n... =  *squiggly hand motion* \nc = uo\nd = pd\ne = qi\nf = jy\ng = ru\nh = sw\nI = xegy\ni = ln\nj = ae\nk = na\nl = rt\nm = wu\nn = is\no = nd\np = hw\nq = op\nr = kb\ns = vf\nt = fc\nu = xr\nv = ex\nw = mn\nx = gb\ny = bu\nz = ie\n. =  *right wing slash* \n, =  *hand wave* \n" =  *hand curve* \n! =  *double hand jerk* \n? =  *wing wave* '
  2. repl={}
  3. reverse_repl={}
  4. import sys
  5. #Generate replacement tables
  6. for str in foo.split("\n"):
  7.     parts=str.split(" = ")
  8.     repl[parts[0]]=parts[1]
  9.     repl[parts[0].lower()]=parts[1]
  10.     reverse_repl[parts[1]]=parts[0]
  11. def encipher():
  12.     outstr = ''
  13.     instr = sys.stdin.readline()
  14.     i = 0
  15.     n = len(instr)
  16.     while i < n:
  17.         c = instr[i] 
  18.         if instr[i:i+3] == '...': 
  19.             outstr += repl['...'] 
  20.             i+=3 
  21.         elif c in repl: 
  22.             outstr += repl[c] 
  23.             i+=1 
  24.         else: 
  25.             outstr += c
  26.             i+=1
  27.     print outstr
  28. def decipher():
  29.     outstr = ''
  30.     instr = sys.stdin.readline()
  31.     i = 0
  32.     n = len(instr)
  33.     while i < n:
  34.         if instr[i:i+2] in reverse_repl:
  35.             outstr+=reverse_repl[instr[i:i+2]]
  36.             i+=2
  37.         else:
  38.             outstr+=instr[i]
  39.             i+=1
  40.     print outstr
  41. if (sys.argv[1]=="-e"):
  42.     encipher()
  43. else:
  44.     decipher()
  45. raw_input('press Return to end program>')
Enciphering works perfectly (that "..." fix was great), but now with deciphering, there are a couple values that take up more than 2 letters.

These include:
*right wing slash* = .
*hand wave* = ,
*hand curve* = "
*double hand jerk* = !
*wing wave* = ?
*squiggly hand motion* = ...
xegy = I

Is there a more efficient way than searching for each one individually? (Maybe from an array or something?)
Dec 14 '08 #3

bvdet
Expert Mod 2.5K+
P: 2,851
You should consider processing these special cases separately. Example:
Expand|Select|Wrap|Line Numbers
  1. dd = {'*right wing slash*': '.',
  2.       '*hand wave*': ',',
  3.       '*hand curve*': '"',
  4.       '*double hand jerk*': '!',
  5.       '*wing wave*': '?',
  6.       '*squiggly hand motion*': '...',
  7.       'xegy': 'I'}
  8.  
  9. def fix_str(s):
  10.     for key in dd:
  11.         s = s.replace(key, dd[key])
  12.     return s
Expand|Select|Wrap|Line Numbers
  1. >>> print fix_str("*right wing slash**hand wave**hand curve*")
  2. .,"
  3. >>> 
Dec 14 '08 #4

P: 9
2 digit encryption...the closest thing to this will be the BIFID cipher

try reading this: http://en.wikipedia.org/wiki/Bifid_cipher

it should give you a good idea on the algorithm
Mar 2 '09 #5

Post your reply

Sign in to post your reply or Sign up for a free account.