94 lines
1.6 KiB
Go
94 lines
1.6 KiB
Go
package psyfer
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
var charFreq = []float64{
|
|
0.080,
|
|
0.015,
|
|
0.030,
|
|
0.040,
|
|
0.130,
|
|
0.020,
|
|
0.015,
|
|
0.060,
|
|
0.065,
|
|
0.005,
|
|
0.005,
|
|
0.035,
|
|
0.030,
|
|
0.070,
|
|
0.080,
|
|
0.020,
|
|
0.002,
|
|
0.065,
|
|
0.060,
|
|
0.090,
|
|
0.030,
|
|
0.010,
|
|
0.015,
|
|
0.005,
|
|
0.020,
|
|
0.002,
|
|
}
|
|
|
|
func pc(position, i int) int {
|
|
if position-i < 0 {
|
|
return 26 - (int(math.Abs(float64((position - i) % 26))))
|
|
} else {
|
|
return int(math.Abs(float64((position - i) % 26)))
|
|
}
|
|
}
|
|
|
|
func (p phi) String() string {
|
|
return fmt.Sprintf("%d %f\n", p.position, p.value)
|
|
}
|
|
|
|
type phi struct {
|
|
position int
|
|
value float64
|
|
}
|
|
|
|
type allPhi []phi
|
|
|
|
func (p allPhi) Len() int { return len(p) }
|
|
func (p allPhi) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
|
func (p allPhi) Less(i, j int) bool { return p[i].value < p[j].value }
|
|
|
|
func CharacterFrequency(input string) map[rune]float64 {
|
|
cf := make(map[rune]int)
|
|
freq := make(map[rune]float64)
|
|
for _, c := range input {
|
|
cf[c]++
|
|
}
|
|
l := len(input)
|
|
for c, n := range cf {
|
|
freq[c] = float64(n) / float64(l)
|
|
}
|
|
return freq
|
|
}
|
|
|
|
func Guess(input string) {
|
|
alphabet := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
input = strings.ToUpper(strings.Replace(input, " ", "", -1))
|
|
freq := CharacterFrequency(input)
|
|
total := []phi{}
|
|
for i := 0; i < 26; i++ {
|
|
a := 0.0
|
|
for c, n := range freq {
|
|
index := int(c - 'A')
|
|
a += n * charFreq[pc(index, i)]
|
|
}
|
|
p := phi{i, a}
|
|
total = append(total, p)
|
|
}
|
|
sort.Sort(allPhi(total))
|
|
for i := len(total) - 1; i > len(total)-6; i-- {
|
|
fmt.Println(VigenereCipher(input, string(alphabet[total[i].position]), true))
|
|
}
|
|
}
|