Files
coding/state/state.go

92 lines
1.5 KiB
Go
Raw Normal View History

2023-12-30 20:14:01 -07:00
package state
import (
"fmt"
"strings"
)
type node struct {
symbol byte
count int
2023-12-31 14:28:28 -08:00
index int
2023-12-30 20:14:01 -07:00
}
type State struct {
2023-12-31 14:15:10 -08:00
nodes []*node
2023-12-31 14:28:28 -08:00
bySymbol map[byte]*node
2023-12-30 20:14:01 -07:00
}
func NewState() *State {
st := &State{
2023-12-31 14:28:28 -08:00
bySymbol: map[byte]*node{},
2023-12-30 20:14:01 -07:00
}
for i := 0; i < 256; i++ {
2023-12-31 14:15:10 -08:00
node := &node{
symbol: byte(i),
2023-12-31 14:28:28 -08:00
index: i,
2023-12-31 14:15:10 -08:00
}
st.nodes = append(st.nodes, node)
2023-12-31 14:28:28 -08:00
st.bySymbol[node.symbol] = node
2023-12-30 20:14:01 -07:00
}
return st
}
func (st State) Clone() *State {
2023-12-31 14:15:10 -08:00
st2 := &State{
2023-12-31 14:28:28 -08:00
bySymbol: map[byte]*node{},
2023-12-30 20:14:01 -07:00
}
2023-12-31 14:15:10 -08:00
for _, node := range st.nodes {
tmp := *node
st2.nodes = append(st2.nodes, &tmp)
2023-12-31 14:28:28 -08:00
st2.bySymbol[tmp.symbol] = &tmp
2023-12-31 14:15:10 -08:00
}
return st2
2023-12-30 20:14:01 -07:00
}
// Returns old index
func (st *State) IncrementSymbol(symbol byte) int {
2023-12-31 14:41:26 -08:00
node := st.nodeFromSymbol(symbol)
2023-12-31 14:28:28 -08:00
node.count++
origIndex := node.index
2023-12-30 20:14:01 -07:00
2023-12-31 14:28:28 -08:00
for iterIndex := origIndex; iterIndex > 0; iterIndex-- {
2023-12-30 20:14:01 -07:00
prevIndex := iterIndex - 1
iterNode := st.nodes[iterIndex]
prevNode := st.nodes[prevIndex]
if prevNode.count > iterNode.count {
break
} else if prevNode.count == iterNode.count && prevNode.symbol < iterNode.symbol {
break
}
2023-12-31 14:28:28 -08:00
st.nodes[iterNode.index], st.nodes[prevNode.index] = prevNode, iterNode
prevNode.index, iterNode.index = iterIndex, prevIndex
2023-12-30 20:14:01 -07:00
}
2023-12-31 14:28:28 -08:00
return origIndex
2023-12-30 20:14:01 -07:00
}
func (st State) String() string {
strs := []string{}
for _, node := range st.nodes {
if node.count == 0 {
break
}
strs = append(strs, fmt.Sprintf("{%#U}=%d", node.symbol, node.count))
}
return strings.Join(strs, ", ")
}
2023-12-31 14:41:26 -08:00
func (st State) nodeFromSymbol(symbol byte) *node {
return st.bySymbol[symbol]
}