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.8 KiB

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