Header

Header

Thursday, May 23, 2019

Converting Python Caesar Cipher to Go Language Part 4

In this post we will continue converting the Caesar Cipher Python program to Go Language.

Let us take a look at the next function:

 def getTranslatedMessage(mode, message, key):  
   if mode[0] == 'd':  
     key = -key  
   translated = ''  
   for symbol in message:  
     if symbol.isalpha():  
       num = ord(symbol)  
       num += key  
       if symbol.isupper():  
         if num > ord('Z'):  
           num -= 26  
         elif num < ord('A'):  
           num += 26  
       elif symbol.islower():  
         if num > ord('z'):  
           num -= 26  
         elif num < ord('a'):  
           num += 26  
       translated += chr(num)  
     else:  
       translated += symbol  
   return translated  

The getTranslatedMessage() function is the heart of the Caesar Cipher program.  The function loops through each character and shifts the character's ASCII value to a value specified by the key variable.

In order to accomplish this task each character must be converted to it's ASCII value, using the ord() method,  https://docs.python.org/2/library/functions.html#ord

The getTranslatedMessage() function takes into consideration if the character is uppercase or lowercase between A-Z or between a - z and converts according. 

If the number is not between A-Z or between a - z then the symbol is not converted, the symbol is just appended to the translated variable.

If the character is between A-Z or between a-z, the ASCII value is converted back into a character using the chr() function.   https://docs.python.org/2/library/functions.html

Let us now take a look at the Go language equivalent:

 func getTranslatedMessage(mode string, message string, key rune) string {  
      if mode[0:len(mode)] == "d" {  
           key = -key  
      }  
      translated := ""  
      for _, symbol := range message {  
           if unicode.IsLetter(symbol) {  
                num := symbol  
                num += key  
                if unicode.IsUpper(symbol) {  
                     if num > 90 { // "Z"  
                          num -= 26  
                     } else if num < 65 { // "A"  
                          num += 26  
                     }  
                } else if unicode.IsLower(symbol) {  
                     if num > 122 { // "z"  
                          num -= 26  
                     } else if num < 97 { // "a"  
                          num += 26  
                     }  
                }  
                translated += string(rune(num))  
           } else {  
                translated += string(rune(symbol))  
           }  
      }  
      return strings.TrimSpace(translated)  
 }  

Let us take a look at the first if statement:

 if mode[0:len(mode)] == "d" {   
       key = -key   
    }   

Here mode is a string that contains one of several answers, e or enabled, d or disabled or b or brute.
The if statement is checking the string as a slice, from the first character to the length of the mode string, (the end of the string).  https://blog.golang.org/go-slices-usage-and-internals

 for _, symbol := range message {   

Go supports a range clause in the for() loop,  http://www.golangprograms.com/for-range-loops.html
As mentioned before the "_" is used to tell the compiler to ignore the iterator.

The symbol variable is typed by the Go compiler to be a rune type, which is used to parse unicode character data and stored unicode ASCII.  Notice that there is no ord() function that is needed.

 if unicode.IsLetter(symbol) {   
         num := symbol   
         num += key   
         if unicode.IsUpper(symbol) {   
            if num &gt; 90 { // "Z"   
              num -= 26   
            } else if num &lt; 65 { // "A"   
              num += 26   
            }   
         } else if unicode.IsLower(symbol) {   
            if num &gt; 122 { // "z"   
              num -= 26   
            } else if num &lt; 97 { // "a"   
              num += 26   
            }   
         }   
         translated += string(rune(num))   
       } else {   
         translated += string(rune(symbol))   
       }   

There is alot going on in the above segment, that is different than Python,  let up review section by section:

Python uses the symbol.isalpha(), symbol.isupper() and symbol.islower() functions to check for alpha characters, check for uppercase and lowercase.  These functions are part of the core language package in Python.

In Go language the unicode package is used to accomplish the same tasks.  But instead of converting a character to an ASCII we can work directly in ASCII as a result of the rune data type.

 if unicode.IsLetter(symbol) {  
                num := symbol  
                num += key  
                if unicode.IsUpper(symbol) {  
                     if num > 90 { // "Z"  
                          num -= 26  
                     } else if num < 65 { // "A"  
                          num += 26  
                     }  
                } else if unicode.IsLower(symbol) {  
                     if num > 122 { // "z"  
                          num -= 26  
                     } else if num < 97 { // "a"  
                          num += 26  
                     }  
                }  
                translated += string(rune(num))  
           } else {  
                translated += string(rune(symbol))  
           }  

You can clearly see this in the if, else if statements.  The Go Program is comparing ASCII values instead of character values.

As a result the Go program must convert from the rune data type back to character format using the string() function.

No comments:

Post a Comment