Cipher/decipher program

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • slurpz
    New Member
    • Dec 2008
    • 2

    Cipher/decipher program

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

    Code:
    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* '
    repl={}
    reverse_repl={}
    import sys
    #Generate replacement tables
    for str in foo.split("\n"):
    	parts=str.split(" = ")
    	repl[parts[0]]=parts[1]
    	repl[parts[0].lower()]=parts[1]
    	reverse_repl[parts[1]]=parts[0]
    def encipher():
    	outstr = ''
    	instr = sys.stdin.readline()
    	i = 0
    	for i in range(len(instr)):
    		c = instr[i]
    		if (instr[i:i+3]=='...'):
    			outstr+=repl['...']
    			i+=3
    		else:
    			if (c in repl):
    				outstr+=repl[c]
    				i+=1
    			else:
    				outstr+=c
    				i+=1
    	print outstr
    def decipher():
    	outstr = ''
    	instr = sys.stdin.readline()
    	instr=instr[:-1]
    	i = 0
    	c = instr[i]
    	while (i<len(instr)):
    			if (instr[i:i+2]):
    				outstr+=reverse_repl[instr[i:i+2]]
    				i+=2
    			else:
    				outstr+=c
    				i+=1
    	print outstr
    if (sys.argv[1]=="-e"):
    	encipher()
    else:
    	decipher()
    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.
  • bvdet
    Recognized Expert Specialist
    • Oct 2006
    • 2851

    #2
    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:
    Code:
        for i in range(len(instr)):
            c = instr[i]
            if (instr[i:i+3]=='...'):
                outstr+=repl['...']
                i+=3
            else:
                if (c in repl):
                    outstr+=repl[c]
                    i+=1
                else:
                    outstr+=c
                    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:
    Code:
        while i < len(instr):
            c = instr[i]
            if instr[i:i+3] == '...':
                outstr += repl['...']
                i+=3
            elif c in repl:
                outstr += repl[c]
                i+=1
            else:
                outstr += c*2
                i+=1


    To get the code to work, I replaced your code:
    Code:
        while (i<len(instr)):
                if (instr[i:i+2]):
                    outstr+=reverse_repl[instr[i:i+2]]
                    i+=2
                else:
                    outstr+=c
                    i+=1
    with the following code:
    Code:
        while i<len(instr):
            if reverse_repl.has_key(instr[i:i+2]):
                outstr += reverse_repl[instr[i:i+2]]
            else:
                outstr += instr[i][0]
            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

    Comment

    • slurpz
      New Member
      • Dec 2008
      • 2

      #3
      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:

      Code:
      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* '
      repl={}
      reverse_repl={}
      import sys
      #Generate replacement tables
      for str in foo.split("\n"):
      	parts=str.split(" = ")
      	repl[parts[0]]=parts[1]
      	repl[parts[0].lower()]=parts[1]
      	reverse_repl[parts[1]]=parts[0]
      def encipher():
      	outstr = ''
      	instr = sys.stdin.readline()
      	i = 0
      	n = len(instr)
      	while i < n:
      		c = instr[i] 
      		if instr[i:i+3] == '...': 
      			outstr += repl['...'] 
      			i+=3 
      		elif c in repl: 
      			outstr += repl[c] 
      			i+=1 
      		else: 
      			outstr += c
      			i+=1
      	print outstr
      def decipher():
      	outstr = ''
      	instr = sys.stdin.readline()
      	i = 0
      	n = len(instr)
      	while i < n:
      		if instr[i:i+2] in reverse_repl:
      			outstr+=reverse_repl[instr[i:i+2]]
      			i+=2
      		else:
      			outstr+=instr[i]
      			i+=1
      	print outstr
      if (sys.argv[1]=="-e"):
      	encipher()
      else:
      	decipher()
      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?)

      Comment

      • bvdet
        Recognized Expert Specialist
        • Oct 2006
        • 2851

        #4
        You should consider processing these special cases separately. Example:
        Code:
        dd = {'*right wing slash*': '.',
              '*hand wave*': ',',
              '*hand curve*': '"',
              '*double hand jerk*': '!',
              '*wing wave*': '?',
              '*squiggly hand motion*': '...',
              'xegy': 'I'}
        
        def fix_str(s):
            for key in dd:
                s = s.replace(key, dd[key])
            return s
        Code:
        >>> print fix_str("*right wing slash**hand wave**hand curve*")
        .,"
        >>>

        Comment

        • MojaveKid
          New Member
          • Sep 2007
          • 9

          #5
          2 digit encryption...th e 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

          Comment

          Working...