Files
coding/state/state.go

75 lines
1.3 KiB
Go
Raw Normal View History

2023-12-30 20:14:01 -07:00
package state
import (
"fmt"
"maps"
"strings"
)
type node struct {
symbol byte
count int
}
type State struct {
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++ {
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 {
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
}
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, ", ")
}