app.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. package weirdtext
  2. import (
  3. "math/rand"
  4. "sort"
  5. "unicode"
  6. )
  7. func encodeWord(word []rune, wordLength int) {
  8. if wordLength == 4 {
  9. word[1], word[2] = word[2], word[1]
  10. return
  11. }
  12. original := string(word)
  13. toShuffle := word[1 : wordLength-1]
  14. toShuffleLength := wordLength - 2
  15. rand.Shuffle(toShuffleLength, func(i, j int) {
  16. toShuffle[i], toShuffle[j] = toShuffle[j], toShuffle[i]
  17. })
  18. if string(word) == original {
  19. rand.Shuffle(toShuffleLength, func(i, j int) {
  20. toShuffle[i], toShuffle[j] = toShuffle[j], toShuffle[i]
  21. })
  22. }
  23. }
  24. //EncodeText returns encoded provided text and sorted array of encoded words
  25. func EncodeText(text string) EncodedText {
  26. runes := []rune(text)
  27. var currentWord []rune
  28. var newString []rune
  29. var encodedWords []string
  30. for _, item := range runes {
  31. if unicode.IsPunct(item) || unicode.IsSpace(item) {
  32. currentWordLength := len(currentWord)
  33. if currentWordLength >= 4 {
  34. beforeEncoding := string(currentWord)
  35. encodeWord(currentWord, currentWordLength)
  36. if string(currentWord) != beforeEncoding {
  37. encodedWords = append(encodedWords, beforeEncoding)
  38. }
  39. }
  40. for _, letter := range currentWord {
  41. newString = append(newString, letter)
  42. }
  43. currentWord = []rune{}
  44. newString = append(newString, item)
  45. continue
  46. }
  47. currentWord = append(currentWord, item)
  48. }
  49. sort.Strings(encodedWords)
  50. return EncodedText{string(newString), encodedWords}
  51. }
  52. func removeString(array []string, index int) []string {
  53. return append(array[:index], array[index+1:]...)
  54. }
  55. func removeRune(array []rune, index int) []rune {
  56. return append(array[:index], array[index+1:]...)
  57. }
  58. func decodeWord(word []rune, wordLength int, encodedWords []string) (string, []string) {
  59. for index, encodedWord := range encodedWords {
  60. encoded := []rune(encodedWord)
  61. if len(encoded) != wordLength {
  62. continue
  63. }
  64. if word[0] != encoded[0] || word[wordLength-1] != encoded[wordLength-1] {
  65. continue
  66. }
  67. found := false
  68. partOfEncoded := encoded[1 : wordLength-1]
  69. for i := 1; i < wordLength-1; i++ {
  70. letterFound := false
  71. for j, letter := range partOfEncoded {
  72. if letter == word[i] {
  73. partOfEncoded = removeRune(partOfEncoded, j)
  74. letterFound = true
  75. break
  76. }
  77. }
  78. if !letterFound {
  79. found = false
  80. break
  81. }
  82. found = true
  83. }
  84. if found {
  85. return encodedWord, removeString(encodedWords, index)
  86. }
  87. }
  88. return string(word), encodedWords
  89. }
  90. //DecodeText returns decoded provided text using provided array of encoded words
  91. func DecodeText(encoded EncodedText) string {
  92. runes := []rune(encoded.Text)
  93. encodedWords := make([]string, len(encoded.EncodedWords))
  94. copy(encodedWords, encoded.EncodedWords)
  95. var currentWord []rune
  96. var newString []rune
  97. for _, item := range runes {
  98. if unicode.IsPunct(item) || unicode.IsSpace(item) {
  99. currentWordLength := len(currentWord)
  100. if currentWordLength >= 4 {
  101. var decoded string
  102. decoded, encodedWords = decodeWord(currentWord, currentWordLength, encodedWords)
  103. currentWord = []rune(decoded)
  104. }
  105. for _, letter := range currentWord {
  106. newString = append(newString, letter)
  107. }
  108. currentWord = []rune{}
  109. newString = append(newString, item)
  110. continue
  111. }
  112. currentWord = append(currentWord, item)
  113. }
  114. return string(newString)
  115. }