package main
import (
"errors"
"fmt"
"reflect"
"regexp"
)
var TBL = []rune("abcdefghijklmnopqrstuvwxyz")
var CLUES = []string{"this", "the", "that"}
var (
ErrLength = errors.New("invalid length")
ErrChar = errors.New("invalid char")
ErrNoClue = errors.New("no clue word")
ErrShift = errors.New("invalid shift value")
)
func Encrypt(in string, sh int) (enc string, err error) {
err = assert(in)
if sh < 0 {
err = ErrShift
}
if err != nil {
return
}
enc = shift(in, sh)
return
}
func Decrypt(in string) (dec string, sh int, err error) {
err = assert(in)
if err != nil {
return
}
var hit bool = false
subin := subStr(in)
for i := 0; i < len(CLUES); i++ {
subclue := subStr(CLUES[i])
for j := 0; j < len(subin)-len(subclue)+1; j++ {
if reflect.DeepEqual(subin[j:j+1], subclue[0:len(subclue)-1]) {
sh = subtract([]rune(in)[j], []rune(CLUES[i])[0])
hit = true
break
}
}
}
if !hit {
err = ErrNoClue
return
}
dec = shift(in, -sh)
return
}
func assert(in string) (err error) {
if regexp.MustCompile(`[^a-z\. \r\n]`).MatchString(in) {
err = ErrChar
} else if len(in) > 80 {
err = ErrLength
}
return
}
func shift(in string, sh int) (out string) {
for _, v := range in {
if v == '.' || v == ' ' || v == '\r' || v == '\n' {
out += string(v)
continue
}
i := indexOf(TBL, v)
len := len(TBL)
var ii int = (i + sh) % len
if ii < 0 {
ii += len
}
if ii > len {
ii -= len
}
out += string(TBL[ii])
}
return
}
func subtract(left rune, right rune) (out int) {
l := indexOf(TBL, left)
r := indexOf(TBL, right)
out = l - r
if out < 0 {
out += len(TBL)
}
return
}
func subStr(in string) []int {
subin := make([]int, 0, 79)
for i := range in {
if i > len(in)-2 {
break
}
subin = append(subin, subtract([]rune(in)[i], []rune(in)[i+1]))
}
// return
return subin
}
func indexOf(target []rune, searchChar rune) int {
for i, v := range target {
if v == searchChar {
return i
}
}
return -1
}
func main() {
in := "xlmw mw xli tmgxyvi xlex m xsso mr xli xvmt."
fmt.Printf("in : '%s'\n", in)
out, sh, err := Decrypt(in)
fmt.Printf("out: '%s'\n", out)
fmt.Printf("sh : %d\n", sh)
fmt.Printf("err: %v\n", err)
}
评论