HiveBrain v1.2.0
Get Started
← Back to all entries
patterngoMinor

My first Go program: Caesar Cipher

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
caesarfirstprogramcipher

Problem

I'm learning Go at this moment and it is my first program in Go, so I will be thankfull for any suggestion, remarks and observations.

package main

import (
    "fmt"
)

const ascii = "abcdefghijklmnopqrstuvwxyz"
var goodness_values = []float32 { .0817,.0149,.0278,.0425,.1270,.0223,.0202, .0609,.0697,.0015,.0077,.0402,.0241,.0675, .0751,.0193,.0009,.0599,.0633,.0906,.0276, .0098,.0236,.0015,.0197,.0007 }

func zip(s1 string, s2 string) map[string]string {
    result := make(map[string] string)

    for i, v := range s1 {
        result[string(v)] = string(s2[i])
    }

    return result
}

func crypt(s string, table map[string]string) string {
    result := ""

    for _, v := range s {
        result += table[string(v)]  
    }

    return result
}

func encode(message string, key int) string {
    shifted_ascii := ascii[key:] + ascii[:key]
    trans_table := zip(ascii, shifted_ascii)

    return crypt(message, trans_table)
}

func decode(secret string, key int) string {
    shifted_ascii := ascii[key:] + ascii[:key]
    trans_table := zip(shifted_ascii, ascii)

    return crypt(secret, trans_table)
}

func goodness(version string, letter_goodness map[string] float32) float32 {
    var result float32 = 0.0

    for _, v := range version {
        result += letter_goodness[string(v)]
    }

    return result
}

func crack(secret string) string {
    var best_score float32  = 0.0
    result := ""
    letter_goodness := make(map[string] float32)

    for i, v := range ascii {
        letter_goodness[string(v)] = goodness_values[i]
    }

    for i := 0; i  best_score) {
            best_score = score
            result = version
        }
    }

    return result
}

func main() {
    fmt.Printf("%s\n", encode("hello", 10))
    fmt.Printf("%s\n", decode("rovvy", 10))
    fmt.Printf("%s\n", crack("pybrscpexnkwoxdkvmyxdbsledsyxcdydronopsxsdsyxkxnnocsqxypzbyqbkwwsxqvkxqekqoc"))
}

Solution

It looks like it was written in another language and then translated to Go. It looks complicated. Go is designed to be efficient. Maps are not as efficient as slices and arrays for simple indexing. decode(secret, i) executes 26 times instead of once. Etc.

Here's an alternate version,

package main

import "fmt"

const alphabet = "abcdefghijklmnopqrstuvwxyz"

func rotate(s string, rot int) string {
    rot %= 26
    b := []byte(s)
    for i, c := range b {
        c |= 0x20
        if 'a'  maxsum {
            maxsum = sum
            maxi = i
        }
    }
    return rotate(cipher, maxi)
}

func main() {
    fmt.Printf("%s\n", encode("hello", 10))
    fmt.Printf("%s\n", decode("rovvy", 10))
    fmt.Printf("%s\n", crack("pybrscpexnkwoxdkvmyxdbsledsyxcdydronopsxsdsyxkxnnocsqxypzbyqbkwwsxqvkxqekqoc"))
}


Output:

rovvy
hello
forhisfundamentalcontributionstothedefinitionanddesignofprogramminglanguages

Code Snippets

package main

import "fmt"

const alphabet = "abcdefghijklmnopqrstuvwxyz"

func rotate(s string, rot int) string {
    rot %= 26
    b := []byte(s)
    for i, c := range b {
        c |= 0x20
        if 'a' <= c && c <= 'z' {
            b[i] = alphabet[(int(('z'-'a'+1)+(c-'a'))+rot)%26]
        }
    }
    return string(b)
}

func decode(cipher string, rot int) (text string) {
    return rotate(cipher, -rot)
}

func encode(text string, rot int) (cipher string) {
    return rotate(text, rot)
}

var frequencies = []float32{
    .0817, .0149, .0278, .0425, .1270, .0223, .0202, .0609, .0697, .0015, .0077, .0402, .0241,
    .0675, .0751, .0193, .0009, .0599, .0633, .0906, .0276, .0098, .0236, .0015, .0197, .0007,
}

func crack(cipher string) (text string) {
    var sums [26]float32
    for _, c := range cipher {
        c |= 0x20
        for j := range sums {
            if 'a' <= c && c <= 'z' {
                sums[j] += frequencies[(int(c)-int('a')+j)%26]
            }
        }
    }
    var maxi, maxsum = 0, float32(0)
    for i, sum := range sums {
        if sum > maxsum {
            maxsum = sum
            maxi = i
        }
    }
    return rotate(cipher, maxi)
}

func main() {
    fmt.Printf("%s\n", encode("hello", 10))
    fmt.Printf("%s\n", decode("rovvy", 10))
    fmt.Printf("%s\n", crack("pybrscpexnkwoxdkvmyxdbsledsyxcdydronopsxsdsyxkxnnocsqxypzbyqbkwwsxqvkxqekqoc"))
}
rovvy
hello
forhisfundamentalcontributionstothedefinitionanddesignofprogramminglanguages

Context

StackExchange Code Review Q#18080, answer score: 3

Revisions (0)

No revisions yet.