Publish as versioned Gitea module; move dictionary pipeline out
- Rename module to gitea.iliadenisov.ru/developer/scrabble-solver so it can be consumed as a versioned dependency (no go.work replace / CI clone). - De-internalize wordlist and dictdawg as public packages. - Remove cmd/builddict, dictprep/, the dictionaries submodule and the dawg Makefile: the word-list parsing and DAWG build now live in the separate scrabble-dictionary repository, which publishes the DAWG set as a release artifact. - internal/dict loads the committed dawg/en_sowpods.dawg fixture for cmd/stress. - Update README/CLAUDE docs accordingly.
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
// Package dictdawg builds a plain left-to-right DAWG of a dictionary, as used by the
|
||||
// Appel-Jacobson move generator.
|
||||
package dictdawg
|
||||
|
||||
import (
|
||||
"github.com/iliadenisov/alphabet"
|
||||
dawg "github.com/iliadenisov/dafsa"
|
||||
)
|
||||
|
||||
// Build returns a DAWG Finder over words, which must be alphabet-index slices sorted by
|
||||
// index order and de-duplicated (see wordlist.Encode).
|
||||
func Build(idx alphabet.Indexer, words [][]byte) (dawg.Finder, error) {
|
||||
d := dawg.New(idx)
|
||||
for _, w := range words {
|
||||
if err := d.AddB(w); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return d.Finish(), nil
|
||||
}
|
||||
|
||||
// Save writes the DAWG to filename. It requires an embedded alphabet (for example
|
||||
// alphabet.Latin()), so that Load can reconstruct it.
|
||||
func Save(f dawg.Finder, filename string) error {
|
||||
_, err := f.Save(filename)
|
||||
return err
|
||||
}
|
||||
|
||||
// Load reopens a DAWG saved with Save.
|
||||
func Load(filename string) (dawg.Finder, error) { return dawg.Load(filename) }
|
||||
@@ -0,0 +1,44 @@
|
||||
package dictdawg_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/iliadenisov/alphabet"
|
||||
|
||||
"gitea.iliadenisov.ru/developer/scrabble-solver/dictdawg"
|
||||
"gitea.iliadenisov.ru/developer/scrabble-solver/wordlist"
|
||||
)
|
||||
|
||||
func TestBuildAndQuery(t *testing.T) {
|
||||
words := wordlist.Encode([]string{"care", "cares", "cat"}, alphabet.Latin(), 2, 15)
|
||||
f, err := dictdawg.Build(alphabet.Latin(), words)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if f.NumAdded() != 3 {
|
||||
t.Fatalf("NumAdded = %d, want 3", f.NumAdded())
|
||||
}
|
||||
if i := f.IndexOfB([]byte{2, 0, 17, 4}); i != 0 { // care
|
||||
t.Errorf("IndexOf(care) = %d, want 0", i)
|
||||
}
|
||||
if i := f.IndexOfB([]byte{2, 0, 19}); i != 2 { // cat
|
||||
t.Errorf("IndexOf(cat) = %d, want 2", i)
|
||||
}
|
||||
if i := f.IndexOfB([]byte{2, 0, 17}); i != -1 { // car (absent)
|
||||
t.Errorf("IndexOf(car) = %d, want -1", i)
|
||||
}
|
||||
|
||||
path := filepath.Join(t.TempDir(), "d.dawg")
|
||||
if err := dictdawg.Save(f, path); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
g, err := dictdawg.Load(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer g.Close()
|
||||
if i := g.IndexOfB([]byte{2, 0, 17, 4, 18}); i != 1 { // cares
|
||||
t.Errorf("loaded IndexOf(cares) = %d, want 1", i)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user