95 lines
1.8 KiB
Go
95 lines
1.8 KiB
Go
|
package main
|
|||
|
|
|||
|
import "math"
|
|||
|
|
|||
|
var (
|
|||
|
alphabet = []rune("АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ")
|
|||
|
alphabetLen = len(alphabet)
|
|||
|
|
|||
|
alphabetFreq = []float64{ // took from https://dpva.ru/Guide/GuideUnitsAlphabets/Alphabets/FrequencyRuLetters/ (without Ë)
|
|||
|
0.080159, // А
|
|||
|
0.015942, // Б
|
|||
|
0.045400, // ...
|
|||
|
0.016957,
|
|||
|
0.029801,
|
|||
|
0.084523,
|
|||
|
0.009398,
|
|||
|
0.016492,
|
|||
|
0.073559,
|
|||
|
0.012090,
|
|||
|
0.034952,
|
|||
|
0.044013,
|
|||
|
0.032080,
|
|||
|
0.066997,
|
|||
|
0.109714,
|
|||
|
0.028117,
|
|||
|
0.047352,
|
|||
|
0.054698,
|
|||
|
0.062606,
|
|||
|
0.026225,
|
|||
|
0.002645,
|
|||
|
0.009710,
|
|||
|
0.004829,
|
|||
|
0.014453,
|
|||
|
0.007283,
|
|||
|
0.003608,
|
|||
|
0.000367,
|
|||
|
0.018999,
|
|||
|
0.017392,
|
|||
|
0.003188,
|
|||
|
0.006377,
|
|||
|
0.020074,
|
|||
|
}
|
|||
|
|
|||
|
mostFrequest = []rune("ОЕАИНТСРВЛК")
|
|||
|
)
|
|||
|
|
|||
|
type Coder struct {
|
|||
|
ToCode map[rune]int
|
|||
|
ToRune map[int]rune
|
|||
|
RuFreq map[rune]float64
|
|||
|
}
|
|||
|
|
|||
|
func NewCoder() Coder {
|
|||
|
coder := Coder{
|
|||
|
ToCode: make(map[rune]int, alphabetLen),
|
|||
|
ToRune: make(map[int]rune, alphabetLen),
|
|||
|
RuFreq: make(map[rune]float64, alphabetLen),
|
|||
|
}
|
|||
|
|
|||
|
for i, r := range alphabet {
|
|||
|
coder.ToCode[r] = i
|
|||
|
coder.ToRune[i] = r
|
|||
|
coder.RuFreq[r] = alphabetFreq[i]
|
|||
|
}
|
|||
|
|
|||
|
return coder
|
|||
|
}
|
|||
|
|
|||
|
// Code with xor encoding.
|
|||
|
func (c Coder) Code(text, key []rune) []rune {
|
|||
|
res := make([]rune, 0, len(text))
|
|||
|
for i, r := range text {
|
|||
|
keyIndex := i % len(key)
|
|||
|
res = append(res, rune(c.ToRune[c.ToCode[r]^c.ToCode[key[keyIndex]]]))
|
|||
|
}
|
|||
|
return res
|
|||
|
}
|
|||
|
|
|||
|
func (c Coder) RuneFrequency(text, key []rune) map[rune]int {
|
|||
|
res := make(map[rune]int, alphabetLen)
|
|||
|
for i, r := range text {
|
|||
|
keyIndex := i % len(key)
|
|||
|
res[rune(c.ToRune[c.ToCode[r]^c.ToCode[key[keyIndex]]])] += 1
|
|||
|
}
|
|||
|
return res
|
|||
|
}
|
|||
|
|
|||
|
func (c Coder) AlphabetDivergence(analysis map[rune]int, textLen float64) float64 {
|
|||
|
var result float64
|
|||
|
for r, freq := range analysis {
|
|||
|
result += math.Abs(float64(freq)/textLen - c.RuFreq[r])
|
|||
|
}
|
|||
|
return result
|
|||
|
}
|