Skip to content
Permalink
Browse files
Initial
  • Loading branch information
Paul Boyd committed Jul 20, 2018
0 parents commit b533f93
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 0 deletions.
@@ -0,0 +1,80 @@
package markov

type Builder struct {
nodes map[interface{}]*builderNode
}

func NewBuilder() *Builder {
return &Builder{
nodes: make(map[interface{}]*builderNode, 1),
}
}

func (b *Builder) Build() []*Node {
nodes := make(map[interface{}]*Node, len(b.nodes))

for value, _ := range b.nodes {
nodes[value] = &Node{
Value: value,
}
}

nodeSlice := make([]*Node, 0, len(b.nodes))

for value, bn := range b.nodes {
node := nodes[value]
node.Children = make([]NodeProbability, 0, len(bn.counts))

for nextValue, probability := range bn.Probabilities() {
node.Children = append(node.Children, NodeProbability{
Node: nodes[nextValue],
Probability: probability,
})
}

nodeSlice = append(nodeSlice, node)
}

return nodeSlice
}

func (b *Builder) Feed(values <-chan interface{}) {
last := b.getNode(nil)

for val := range values {
last.counts[val]++
last = b.getNode(val)
}
}

func (b *Builder) getNode(value interface{}) *builderNode {
node, ok := b.nodes[value]
if !ok {
node = &builderNode{
counts: make(map[interface{}]int, 1),
}

b.nodes[value] = node
}

return node
}

type builderNode struct {
counts map[interface{}]int
}

func (bn *builderNode) Probabilities() map[interface{}]float64 {
sum := 0
for _, c := range bn.counts {
sum += c
}

values := make(map[interface{}]float64, len(bn.counts))

for value, count := range bn.counts {
values[value] = float64(count) / float64(sum)
}

return values
}
@@ -0,0 +1,34 @@
package markov

import (
"testing"
"unicode"
)

func TestFeed(t *testing.T) {
b := NewBuilder()
runes := split(`“Well, Prince, so Genoa and Lucca are now just family estates of the Buonapartes. But I warn you, if you don’t tell me that this means war, if you still try to defend the infamies and horrors perpetrated by that Antichrist—I really believe he is Antichrist—I will have nothing more to do with you and you are no longer my friend, no longer my ‘faithful slave,’ as you call yourself! But how do you do? I see I have frightened you—sit down and tell me all the news.”`)

b.Feed(runes)

nodes := b.Build()

if len(nodes) != 24 {
t.Errorf("got %d nodes, want 24", len(nodes))
}
}

func split(text string) <-chan interface{} {
runes := make(chan interface{})

go func() {
defer close(runes)
for _, r := range text {
if unicode.IsLetter(r) || unicode.IsSpace(r) {
runes <- unicode.ToLower(r)
}
}
}()

return runes
}
@@ -0,0 +1,11 @@
package markov

type Node struct {
Value interface{}
Children []NodeProbability
}

type NodeProbability struct {
*Node
Probability float64
}

0 comments on commit b533f93

Please sign in to comment.