Skip to content

Commit

Permalink
Improved char frequency strategy.
Browse files Browse the repository at this point in the history
Will rebuild the histogram considering only the remaining valid words.
  • Loading branch information
archy-bold committed Jan 6, 2022
1 parent 5a0d174 commit 40c3b42
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 44 deletions.
7 changes: 4 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ func main() {

var strat strategy.Strategy
if auto {
strat = strategy.NewCharFrequencyStrategy(NUM_LETTERS, letters, &validWords, *starterPtr)
strat = strategy.NewCharFrequencyStrategy(NUM_LETTERS, letters, validWords, *starterPtr)
}

// Play out all permutations
if *allPtr {
sumTries := 0
numSuccesses := 0
for _, answer := range validWords {
strat = strategy.NewCharFrequencyStrategy(NUM_LETTERS, letters, &validWords, *starterPtr)
strat = strategy.NewCharFrequencyStrategy(NUM_LETTERS, letters, validWords, *starterPtr)
g := game.CreateGame(answer, NUM_ATTEMPTS, &allAcceptedWords)

for {
Expand Down Expand Up @@ -97,7 +97,7 @@ func main() {

// Cheat mode
if *cheatPtr {
strat = strategy.NewCharFrequencyStrategy(NUM_LETTERS, letters, &validWords, *starterPtr)
strat = strategy.NewCharFrequencyStrategy(NUM_LETTERS, letters, validWords, *starterPtr)
ug := game.CreateUnknownGame(NUM_LETTERS, NUM_ATTEMPTS)
for {

Expand Down Expand Up @@ -192,6 +192,7 @@ func main() {
word = strings.TrimSpace(input)
}

// TODO handle error here
success, _ := g.Play(word)

if strat != nil {
Expand Down
94 changes: 53 additions & 41 deletions strategy/charfrequency.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,65 @@ type CharFrequencyStrategy struct {
starter string
wordLength int
letters map[string]bool
validWords *[]string
possibleAnswers []string
histogram map[string]HistogramEntry
rankedWords PairList
answersCorrect []string
answersIncorrect [][]string
answersIncorrectAll []string
}

func (s *CharFrequencyStrategy) filterWords(hint []game.GridCell) {
filteredWords := make([]string, 0)

word:
for _, word := range s.possibleAnswers {
chrs := strings.Split(word, "")

// Filter any words where incorrect characters don't exist
if len(s.answersIncorrectAll) > 0 {
diff := difference(s.answersIncorrectAll, chrs)
if len(diff) > 0 {
continue word
}
}

for i, chr := range chrs {
// Filter out if this char has been eliminated
if !s.letters[chr] {
continue word
}

// Filter out if this is position has been found to be correct and this char doesn't match
if s.answersCorrect[i] != "" && s.answersCorrect[i] != chr {
continue word
}

// Also filter out if there's an incorrect answer in this position
if len(s.answersIncorrect[i]) > 0 {
for _, ai := range s.answersIncorrect[i] {
if ai == chr {
continue word
}
}
}
}

// Add to the list if the word is still possible
filteredWords = append(filteredWords, word)
}

s.possibleAnswers = filteredWords
}

func (s *CharFrequencyStrategy) buildHistogram() {
s.histogram = make(map[string]HistogramEntry, len(s.letters))
for l := range s.letters {
s.histogram[l] = HistogramEntry{0, make([]int, s.wordLength)}
}

// Loop through each word and check which unique letters are in the word
for _, word := range *s.validWords {
for _, word := range s.possibleAnswers {
chrs := strings.Split(word, "")

// Loop through each char and update the histogram
Expand All @@ -58,48 +101,15 @@ func (s *CharFrequencyStrategy) buildHistogram() {
}

func (s *CharFrequencyStrategy) rankWords() {
s.rankedWords = make(PairList, len(*s.validWords))
s.rankedWords = make(PairList, len(s.possibleAnswers))

word:
for _, word := range *s.validWords {
for _, word := range s.possibleAnswers {
chrs := strings.Split(word, "")
// First set the score based on the letters that exist
// TODO score based on letter position too
checkedChars := map[string]bool{}
score := 0

// Check if any of the incorrect answers don't appear in the word
if len(s.answersIncorrectAll) > 0 {
diff := difference(s.answersIncorrectAll, chrs)
if len(diff) > 0 {
s.rankedWords = append(s.rankedWords, Pair{word, 0})
continue word
}
}

for i, chr := range chrs {
// If this is an eliminated letter, score down
if !s.letters[chr] {
s.rankedWords = append(s.rankedWords, Pair{word, 0})
continue word
}

// If there is an answer in this position, we can disregard words that don't have that letter in that position
if s.answersCorrect[i] != "" && s.answersCorrect[i] != chr {
s.rankedWords = append(s.rankedWords, Pair{word, 0})
continue word
}

// Also check if there's an incorrect answer in this position
if len(s.answersIncorrect[i]) > 0 {
for _, ai := range s.answersIncorrect[i] {
if ai == chr {
s.rankedWords = append(s.rankedWords, Pair{word, 0})
continue word
}
}
}

if _, ok := checkedChars[chr]; !ok {
// Score based on occurences and occurences in the position
scoreToAdd := s.histogram[chr].Occurences + (s.histogram[chr].OccurrencesInPosition[i] * 10)
Expand Down Expand Up @@ -128,12 +138,14 @@ func (s *CharFrequencyStrategy) GetNextMove() string {
if s.attempts == 0 && s.starter != "" {
return s.starter
}
// else if s.attempts == 1 {
// return "crony"
// }
return s.rankedWords[0].Key
}

func (s *CharFrequencyStrategy) SetMoveOutcome(row []game.GridCell) {
// Update the internal state for the row
numCorrect := 0
rejected := make([]bool, s.wordLength)
for i, cell := range row {
switch cell.Status {
Expand All @@ -154,13 +166,13 @@ func (s *CharFrequencyStrategy) SetMoveOutcome(row []game.GridCell) {
s.answersIncorrectAll = append(s.answersIncorrectAll, cell.Letter)
case game.STATUS_CORRECT:
s.answersCorrect[i] = cell.Letter
numCorrect++
}
}

s.attempts++

// Rebuild the histogram and ranking
s.filterWords(row)
s.buildHistogram()
s.rankWords()
}
Expand All @@ -171,7 +183,7 @@ func (s *CharFrequencyStrategy) GetSuggestions(n int) PairList {
}

// NewCharFrequencyStrategy create a char frequency-based strategy given the word list and letters list
func NewCharFrequencyStrategy(wordLength int, letters []string, validWords *[]string, starter string) Strategy {
func NewCharFrequencyStrategy(wordLength int, letters []string, validAnswers []string, starter string) Strategy {
lettersMap := map[string]bool{}
for _, l := range letters {
lettersMap[l] = true
Expand All @@ -181,7 +193,7 @@ func NewCharFrequencyStrategy(wordLength int, letters []string, validWords *[]st
starter: starter,
wordLength: wordLength,
letters: lettersMap,
validWords: validWords,
possibleAnswers: validAnswers,
answersCorrect: make([]string, wordLength),
answersIncorrect: make([][]string, wordLength),
}
Expand Down

0 comments on commit 40c3b42

Please sign in to comment.