Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/JohnDelisle/wordle
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnDelisle committed Feb 16, 2022
2 parents 0f5b32e + a2d103e commit 9bcb138
Show file tree
Hide file tree
Showing 2 changed files with 273 additions and 35 deletions.
70 changes: 35 additions & 35 deletions wordle.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,45 +340,45 @@ func main() {
fmt.Printf("%s %d\n", kv.Key, kv.Value)
}
fmt.Println("------")
/*
/////////////// top X scored trips
topX = 1000
fmt.Printf("--- top %d scored trips ---\n", topX)
// score the trips
scoredTrips := scoreTrips(scoredWords)
// sort the scored pairs
sortedScoredTrips := sortScoredThings(scoredTrips)
// need to be within slice bounds
currentLength = len(sortedScoredTrips)
if topX > currentLength {
topX = currentLength
}
/////////////// top X scored trips
topX = 1000

fmt.Printf("--- top %d scored trips ---\n", topX)
// score the trips
scoredTrips := scoreTrips(scoredWords)
// sort the scored pairs
sortedScoredTrips := sortScoredThings(scoredTrips)

// need to be within slice bounds
currentLength = len(sortedScoredTrips)
if topX > currentLength {
topX = currentLength
}

for _, kv := range sortedScoredTrips[0:topX] {
fmt.Printf("%s %d\n", kv.Key, kv.Value)
}
fmt.Println("------")
for _, kv := range sortedScoredTrips[0:topX] {
fmt.Printf("%s %d\n", kv.Key, kv.Value)
}
fmt.Println("------")
/////////////// top X scored quads
topX = 1000
/////////////// top X scored quads
topX = 1000
fmt.Printf("--- top %d scored quads ---\n", topX)
// score the trips
scoredQuads := scoreQuads(scoredWords)
// sort the scored pairs
sortedScoredQuads := sortScoredThings(scoredQuads)
fmt.Printf("--- top %d scored quads ---\n", topX)
// score the trips
scoredQuads := scoreQuads(scoredWords)
// sort the scored pairs
sortedScoredQuads := sortScoredThings(scoredQuads)
// need to be within slice bounds
currentLength = len(sortedScoredQuads)
if topX > currentLength {
topX = currentLength
}
// need to be within slice bounds
currentLength = len(sortedScoredQuads)
if topX > currentLength {
topX = currentLength
}
for _, kv := range sortedScoredQuads[0:topX] {
fmt.Printf("%s %d\n", kv.Key, kv.Value)
}
fmt.Println("------")
for _, kv := range sortedScoredQuads[0:topX] {
fmt.Printf("%s %d\n", kv.Key, kv.Value)
}
fmt.Println("------") */

}
238 changes: 238 additions & 0 deletions wordleparallel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
package main

import (
"bufio"
"fmt"
"log"
"os"
"sort"
"strings"
"sync"
)

type kv struct {
Key string
Value int
}

func initLetters() map[rune]int {
var letters = make(map[rune]int)
for letter := 'a'; letter <= 'z'; letter++ {
letters[letter] = 0
}
return letters
}

func initWords(path string) (map[string]int, error) {
var words = make(map[string]int)

file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()

scanner := bufio.NewScanner(file)
for scanner.Scan() {
if hasDupeLetters(scanner.Text()) {
// skip words that are low-value starting words..
continue
}
words[scanner.Text()] = 0
}
return words, scanner.Err()
}

func scoreLetters(letters map[rune]int, words map[string]int) map[rune]int {
for letter := range letters {
for word := range words {
if strings.ContainsRune(word, letter) {
letters[letter]++
}
}
}
return letters
}

func scoreWord(word string, letters map[rune]int) int {
var tested string
var score int = 0
for _, letter := range word {
if string(letter) == "," {
continue
}
// only score each letter once
if strings.ContainsRune(tested, letter) {
continue
}
tested = tested + string(letter)
score = score + letters[letter]
}
return score
}

func scoreWords(letters map[rune]int, words map[string]int) map[string]int {
var scoredWords = make(map[string]int)
for word := range words {
scoredWords[word] = scoreWord(word, letters)
}
return scoredWords
}

func sortScoredThings(scoredThings map[string]int) []kv {
var sortedScoredThings []kv

for k, v := range scoredThings {
sortedScoredThings = append(sortedScoredThings, kv{k, v})
}

sort.Slice(sortedScoredThings, func(i, j int) bool {
return sortedScoredThings[i].Value > sortedScoredThings[j].Value
})

return sortedScoredThings
}

func hasDupeLetters(word string) bool {
for _, letter := range word {
if letter == ',' {
continue
}
if strings.Count(word, string(letter)) > 1 {
// fmt.Printf("dupe in word %s, %c\n", word, letter)
return true
}
}

return false
}

func pruneThing(scoredThing map[string]int) map[string]int {
sortedScoredThing := sortScoredThings(scoredThing)

// prune to..
topX := 10000

// need to be within slice bounds
currentLength := len(sortedScoredThing)
if topX > currentLength {
topX = currentLength
}

var prunedSortedScoredThing = make(map[string]int)
for _, kv := range sortedScoredThing[0:topX] {
prunedSortedScoredThing[kv.Key] = kv.Value
}

return prunedSortedScoredThing
}

type safePairs struct {
mu sync.Mutex
v map[string]int
}

func wordTwoWorker(w *sync.WaitGroup, pairs *safePairs, words map[string]int, wordOne string, wordTwos map[string]int) {
for wordTwo := range wordTwos {
pairWord := wordOne + "," + wordTwo
if hasDupeLetters(pairWord) {
continue
}
pairScore := words[wordOne] + words[wordTwo]
pairs.mu.Lock()
pairs.v[pairWord] = pairScore
pairs.mu.Unlock()
}

// too much memory :(
pairs.mu.Lock()
pairs.v = pruneThing(pairs.v)
pairs.mu.Unlock()
w.Done()
}

func scorePairs(words map[string]int) map[string]int {
pairs := safePairs{v: make(map[string]int)}
var w sync.WaitGroup

wordTwos := words
for wordOne := range words {
// remove wordOne, avoid permutatioins like "cat,dog,bat" and "bat,cat,dog"

wordTwos = removeWord(wordOne, wordTwos)
w.Add(1)
go wordTwoWorker(&w, &pairs, words, wordOne, wordTwos)
}
return pairs.v
}

func removeWord(dirtyWord string, words map[string]int) map[string]int {
// strips a word out of the slice..
var cleanWords = make(map[string]int)

for word := range words {
if word != dirtyWord {
cleanWords[word] = words[word]
}
}

return cleanWords
}

func main() {
var topX, currentLength int

// from https://github.com/tabatkins/wordle-list
letters := initLetters()
words, err := initWords("c:\\temp\\wordlewords.txt")

if err != nil {
log.Fatalf("readLines: %s", err)
}

// what'd we read?
fmt.Printf("Read %d words", len(words))

// score and print letters
fmt.Println("--- scored letters ---")
scoredLetters := scoreLetters(letters, words)
for letter, score := range scoredLetters {
fmt.Println(string(letter), score)
}
fmt.Println("------")

/////////////// score words
scoredWords := scoreWords(letters, words)
fmt.Printf("Scored %d words", len(scoredWords))

////////////// top X scored words
topX = 10
fmt.Printf("--- top %d scored words ---\n", topX)
// sort the scored words
sortedScoredWords := sortScoredThings(scoredWords)

for _, kv := range sortedScoredWords[0:topX] {
fmt.Printf("%s %d\n", kv.Key, kv.Value)
}
fmt.Println("------")

/////////////// top X scored pairs
topX = 1000
fmt.Printf("--- top %d scored pairs ---\n", topX)
// score the pairs
scoredPairs := scorePairs(scoredWords)
// sort the scored pairs
sortedScoredPairs := sortScoredThings(scoredPairs)

// need to be within slice bounds
currentLength = len(sortedScoredPairs)
if topX > currentLength {
topX = currentLength
}

for _, kv := range sortedScoredPairs[0:topX] {
fmt.Printf("%s %d\n", kv.Key, kv.Value)
}
fmt.Println("------")

}

0 comments on commit 9bcb138

Please sign in to comment.