Skip to content

Commit

Permalink
Fix word sets including words that don't include center letter
Browse files Browse the repository at this point in the history
Also: removes some swear words from the word list. Whoops!
  • Loading branch information
Gyanreyer committed Jul 6, 2023
1 parent b70b938 commit 0cd0142
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 98 deletions.
67 changes: 34 additions & 33 deletions scripts/generate-word-data.go
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"sort"
"strings"
"unicode"
)

func check(e error) {
Expand Down Expand Up @@ -74,7 +75,11 @@ func main() {
})

if len(uniqueCharKeys) == 7 {
letterSets[string(uniqueCharKeys)] = true
for i := 0; i < 7; i++ {
// Add each permutation of the letter set where one of the letters is capitalized to indicate it's the center letter
letterSet := string(uniqueCharKeys[:i]) + string(unicode.ToUpper(uniqueCharKeys[i])) + string(uniqueCharKeys[i+1:])
letterSets[letterSet] = true
}
}

currentTrieNode := trie
Expand Down Expand Up @@ -107,16 +112,14 @@ func main() {
letterSetResult := <-c
letterSet := letterSetResult.letterSet

for j := 0; j < 7; j++ {
words := letterSetResult.words[j]
wordCount := len(words)
words := letterSetResult.words
wordCount := len(words)

// Only include letter sets with 15-60 words; too few words or too many words aren't as fun
if wordCount >= 10 && wordCount <= 60 {
letterSetWords[letterSet+fmt.Sprintf("%d", j)] = words
for k := 0; k < wordCount; k++ {
uniqueWordIndexMap[words[k]] = -1
}
// Only include letter sets with 25-50 words; too few words or too many words aren't as fun
if wordCount >= 25 && wordCount <= 50 {
letterSetWords[letterSet] = words
for k := 0; k < wordCount; k++ {
uniqueWordIndexMap[words[k]] = -1
}
}
}
Expand Down Expand Up @@ -167,68 +170,66 @@ func main() {

type LetterSetResult struct {
letterSet string
words [][]string
words []string
}

type NodeQueueEntry struct {
parentQueueEntry *NodeQueueEntry
node *TrieNode
hasCenterLetter bool
}

func processLetterSet(letterSet string, rootTrieNode *TrieNode, c chan LetterSetResult) {
nodesToProcess := []*NodeQueueEntry{{parentQueueEntry: nil, node: rootTrieNode}}
// Find the index of the uppercase letter in the letter set, which indicates the center letter
centerLetterIndex := strings.IndexFunc(letterSet, func(r rune) bool {
return unicode.IsUpper(r)
})

wordMap := make([]map[string]bool, 7)
normalizedLetterSet := strings.ToLower(letterSet)
centerLetter := rune(normalizedLetterSet[centerLetterIndex])

nodesToProcess := []*NodeQueueEntry{{parentQueueEntry: nil, node: rootTrieNode, hasCenterLetter: false}}

wordMap := make(map[string]bool)

processedNodeCount := 0
nodeCount := len(nodesToProcess)

letterSetCharIndexMap := make(map[rune]int)
for i, char := range letterSet {
letterSetCharIndexMap[char] = i
}

for processedNodeCount < nodeCount {
currentQueuedNode := nodesToProcess[processedNodeCount]
processedNodeCount++

currentTrieNode := currentQueuedNode.node

for _, char := range letterSet {
for _, char := range normalizedLetterSet {
hasCenterLetter := currentQueuedNode.hasCenterLetter || char == centerLetter

nextTrieNode, ok := currentTrieNode.chars[char]
if ok {
nextQueuedNode := &NodeQueueEntry{
parentQueueEntry: currentQueuedNode,
node: nextTrieNode,
hasCenterLetter: hasCenterLetter,
}
nodesToProcess = append(nodesToProcess, nextQueuedNode)
nodeCount++
}

if len(currentTrieNode.words) == 0 {
if !hasCenterLetter || len(currentTrieNode.words) == 0 {
continue
}

// Add all words from the current node to the word map for the current queued node + all of the characters for its parent queued nodes
for qn := currentQueuedNode; qn != nil; qn = qn.parentQueueEntry {
i := letterSetCharIndexMap[qn.node.char]
for qn := currentQueuedNode; qn != nil && qn.hasCenterLetter; qn = qn.parentQueueEntry {
for _, word := range currentTrieNode.words {
if wordMap[i] == nil {
wordMap[i] = make(map[string]bool)
}

wordMap[i][word] = true
wordMap[word] = true
}
}
}
}

words := make([][]string, 7)

for i := 0; i < 7; i++ {
words[i] = getMapKeys(wordMap[i])
sort.Strings(words[i])
}
words := getMapKeys(wordMap)
sort.Strings(words)

c <- LetterSetResult{letterSet, words}
}
19 changes: 16 additions & 3 deletions src/js/game.mjs
Expand Up @@ -28,6 +28,11 @@ async function openGameDB() {
});
}

/**
* Loads our en.json word data set
*
* @returns {Promise<string[], string[], number[]>}
*/
async function loadWordData() {
const supportsCompressionStream = "DecompressionStream" in window;

Expand Down Expand Up @@ -424,10 +429,18 @@ Alpine.store("game", {

const letterSetIndex = Math.floor(getRandomNumber() * letterSets.length);

const letterSetID = letterSets[letterSetIndex];
const unnormalizedLetterSet = letterSets[letterSetIndex];

const letterSetString = letterSetID.slice(0, -1);
const centerLetterIndex = Number(letterSetID.slice(-1));
// The center letter is marked by being capitalized, so find the first capitalized letter in the set
// (ie, aBcdefg -> center letter is B)
const centerLetterIndex = unnormalizedLetterSet.match(/[A-Z]/)?.index;

if (centerLetterIndex === undefined) {
throw new Error(`Invalid letter set ID "${unnormalizedLetterSet}"`);
}

// Normalize the letter set to all-lowercase
const letterSetString = unnormalizedLetterSet.toLowerCase();

const centerLetter = letterSetString[centerLetterIndex];
const outerLetters = shuffleArray(
Expand Down
2 changes: 1 addition & 1 deletion src/pwa/serviceWorker.js
@@ -1,4 +1,4 @@
const cacheName = "open-spelling-bee-1.2.8";
const cacheName = "open-spelling-bee-1.3.0";
const cacheFiles = [
"/",
"/index.html",
Expand Down
2 changes: 1 addition & 1 deletion src/words/en.json

Large diffs are not rendered by default.

Binary file modified src/words/en.json.gz
Binary file not shown.
60 changes: 0 additions & 60 deletions word-lists/en.txt
Expand Up @@ -6361,17 +6361,6 @@ bister
bisters
bistro
bistros
bitch
bitched
bitches
bitchier
bitchiest
bitchily
bitchiness
bitching
bitchy
bitcoin
bitcoins
bite
biter
biters
Expand Down Expand Up @@ -8439,12 +8428,6 @@ bullring
bullrings
bulls
bullseye
bullshit
bullshits
bullshitted
bullshitter
bullshitters
bullshitting
bullwhip
bullwhips
bully
Expand Down Expand Up @@ -10976,8 +10959,6 @@ chickenhearted
chickening
chickenpox
chickens
chickenshit
chickenshits
chickpea
chickpeas
chicks
Expand Down Expand Up @@ -16089,8 +16070,6 @@ cunning
cunninger
cunningest
cunningly
cunt
cunts
cupboard
cupboards
cupcake
Expand Down Expand Up @@ -27586,14 +27565,6 @@ fryers
frying
fuchsia
fuchsias
fuck
fucked
fucker
fuckers
fuckhead
fuckheads
fucking
fucks
fuddle
fuddled
fuddles
Expand Down Expand Up @@ -32436,7 +32407,6 @@ horsepower
horseradish
horseradishes
horses
horseshit
horseshoe
horseshoed
horseshoeing
Expand Down Expand Up @@ -41813,8 +41783,6 @@ milers
miles
milestone
milestones
milf
milfs
milieu
milieus
militancy
Expand Down Expand Up @@ -43164,9 +43132,6 @@ mother
motherboard
motherboards
mothered
motherfucker
motherfuckers
motherfucking
motherhood
mothering
motherland
Expand Down Expand Up @@ -44490,15 +44455,10 @@ niffy
niftier
niftiest
nifty
nigga
niggard
niggardliness
niggardly
niggards
niggas
niggaz
nigger
niggers
niggle
niggled
niggler
Expand Down Expand Up @@ -50107,14 +50067,6 @@ piscatorial
piscine
pismire
pismires
piss
pissed
pisser
pissers
pisses
pissing
pissoir
pissoirs
pistachio
pistachios
piste
Expand Down Expand Up @@ -61526,17 +61478,6 @@ shirttails
shirtwaist
shirtwaists
shirty
shit
shitfaced
shithead
shitheads
shitload
shits
shitted
shittier
shittiest
shitting
shitty
shiv
shiver
shivered
Expand Down Expand Up @@ -63802,7 +63743,6 @@ sonorous
sonorously
sonorousness
sons
sonsofbitches
soon
sooner
soonest
Expand Down

0 comments on commit 0cd0142

Please sign in to comment.