2023-12-30 20:14:01 -07:00
|
|
|
package state
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"maps"
|
|
|
|
|
"strings"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type node struct {
|
|
|
|
|
symbol byte
|
|
|
|
|
count int
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type State struct {
|
2023-12-30 20:37:18 -08:00
|
|
|
nodes [256]node
|
2023-12-30 20:14:01 -07:00
|
|
|
bySymbol map[byte]int
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewState() *State {
|
|
|
|
|
st := &State{
|
|
|
|
|
bySymbol: map[byte]int{},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for i := 0; i < 256; i++ {
|
2023-12-30 20:37:18 -08:00
|
|
|
st.nodes[i].symbol = byte(i)
|
2023-12-30 20:14:01 -07:00
|
|
|
st.bySymbol[byte(i)] = i
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return st
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (st State) Clone() *State {
|
2023-12-30 20:37:18 -08:00
|
|
|
return &State{
|
|
|
|
|
nodes: st.nodes,
|
2023-12-30 20:14:01 -07:00
|
|
|
bySymbol: maps.Clone(st.bySymbol),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Returns old index
|
|
|
|
|
func (st *State) IncrementSymbol(symbol byte) int {
|
|
|
|
|
nodeIndex := st.bySymbol[symbol]
|
|
|
|
|
st.nodes[nodeIndex].count++
|
|
|
|
|
|
|
|
|
|
for iterIndex := nodeIndex; iterIndex > 0; iterIndex-- {
|
|
|
|
|
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-30 20:37:18 -08:00
|
|
|
st.nodes[iterIndex], st.nodes[prevIndex] = prevNode, iterNode
|
|
|
|
|
st.bySymbol[iterNode.symbol], st.bySymbol[prevNode.symbol] = prevIndex, iterIndex
|
2023-12-30 20:14:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nodeIndex
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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, ", ")
|
|
|
|
|
}
|