You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
2.9 KiB

  1. package main
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "strconv"
  6. "strings"
  7. )
  8. type Markov struct{}
  9. type State struct {
  10. Word string
  11. Count int
  12. Prob float64
  13. NextStates []State
  14. }
  15. var markov Markov
  16. func printLoading(n int, total int) {
  17. var bar []string
  18. tantPerFourty := int((float64(n) / float64(total)) * 40)
  19. tantPerCent := int((float64(n) / float64(total)) * 100)
  20. for i := 0; i < tantPerFourty; i++ {
  21. bar = append(bar, "█")
  22. }
  23. progressBar := strings.Join(bar, "")
  24. fmt.Printf("\r " + progressBar + " - " + strconv.Itoa(tantPerCent) + "")
  25. }
  26. func addWordToStates(states []State, word string) ([]State, int) {
  27. iState := -1
  28. for i := 0; i < len(states); i++ {
  29. if states[i].Word == word {
  30. iState = i
  31. }
  32. }
  33. if iState >= 0 {
  34. states[iState].Count++
  35. } else {
  36. var tempState State
  37. tempState.Word = word
  38. tempState.Count = 1
  39. states = append(states, tempState)
  40. iState = len(states) - 1
  41. }
  42. return states, iState
  43. }
  44. func calcMarkovStates(words []string) []State {
  45. var states []State
  46. //count words
  47. for i := 0; i < len(words)-1; i++ {
  48. var iState int
  49. states, iState = addWordToStates(states, words[i])
  50. if iState < len(words) {
  51. states[iState].NextStates, _ = addWordToStates(states[iState].NextStates, words[i+1])
  52. }
  53. printLoading(i, len(words))
  54. }
  55. //count prob
  56. for i := 0; i < len(states); i++ {
  57. states[i].Prob = (float64(states[i].Count) / float64(len(words)) * 100)
  58. for j := 0; j < len(states[i].NextStates); j++ {
  59. states[i].NextStates[j].Prob = (float64(states[i].NextStates[j].Count) / float64(len(words)) * 100)
  60. }
  61. }
  62. fmt.Println("\ntotal words computed: " + strconv.Itoa(len(words)))
  63. //fmt.Println(states)
  64. return states
  65. }
  66. func textToWords(text string) []string {
  67. s := strings.Split(text, " ")
  68. words := s
  69. return words
  70. }
  71. func (markov Markov) train(text string) []State {
  72. words := textToWords(text)
  73. states := calcMarkovStates(words)
  74. //fmt.Println(states)
  75. return states
  76. }
  77. func getNextMarkovState(states []State, word string) string {
  78. iState := -1
  79. for i := 0; i < len(states); i++ {
  80. if states[i].Word == word {
  81. iState = i
  82. }
  83. }
  84. if iState < 0 {
  85. return "word no exist on the memory"
  86. }
  87. var next State
  88. next = states[iState].NextStates[0]
  89. next.Prob = rand.Float64() * states[iState].Prob
  90. for i := 0; i < len(states[iState].NextStates); i++ {
  91. if (rand.Float64()*states[iState].NextStates[i].Prob) > next.Prob && states[iState-1].Word != states[iState].NextStates[i].Word {
  92. next = states[iState].NextStates[i]
  93. }
  94. }
  95. return next.Word
  96. }
  97. func (markov Markov) generateText(states []State, initWord string, count int) string {
  98. var generatedText []string
  99. word := initWord
  100. generatedText = append(generatedText, word)
  101. for i := 0; i < count; i++ {
  102. word = getNextMarkovState(states, word)
  103. if word == "word no exist on the memory" {
  104. return "word no exist on the memory"
  105. }
  106. generatedText = append(generatedText, word)
  107. }
  108. //generatedText = append(generatedText, ".")
  109. text := strings.Join(generatedText, " ")
  110. return text
  111. }