Skip to content

Instantly share code, notes, and snippets.

@umran
Last active January 10, 2022 04:38
Show Gist options
  • Save umran/56984d0adf8d751821ace36539228131 to your computer and use it in GitHub Desktop.
Save umran/56984d0adf8d751821ace36539228131 to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"fmt"
"log"
"os"
)
var alphabet = []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}
func search(word []string, wordComplement [][]string, expectedChars []string, eliminatedChars []string) []string {
blanks := 0
for _, c := range word {
if c == "" {
blanks++
}
}
pool := filter(alphabet, func(c string) bool {
for _, ec := range eliminatedChars {
if c == ec {
return false
}
}
return true
})
dictionary := genDictionary()
words := make([]string, 0)
forEachCombo(make([]string, 0, blanks), pool, func(combo []string) {
for _, c := range expectedChars {
if !contains(combo, c) {
return
}
}
candidate := ""
j := 0
for i, c := range word {
if c != "" {
candidate += c
continue
}
if wordComplement[i] != nil && contains(wordComplement[i], combo[j]) {
return
}
candidate += combo[j]
j++
}
if _, ok := dictionary[candidate]; ok {
words = append(words, candidate)
}
})
return words
}
func forEachCombo(combo []string, pool []string, f func([]string)) {
if len(combo) == cap(combo) {
f(combo)
return
}
for _, c := range pool {
longerCombo := make([]string, len(combo), cap(combo))
copy(longerCombo, combo)
longerCombo = append(longerCombo, c)
forEachCombo(longerCombo, pool, f)
}
}
func filter(list []string, f func(string) bool) []string {
filtered := make([]string, 0, cap(list))
for _, item := range list {
if f(item) {
filtered = append(filtered, item)
}
}
return filtered
}
func contains(list []string, value string) bool {
for _, item := range list {
if item == value {
return true
}
}
return false
}
func genDictionary() map[string]struct{} {
file, err := os.Open("words.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
dictionary := make(map[string]struct{})
scanner := bufio.NewScanner(file)
for scanner.Scan() {
dictionary[scanner.Text()] = struct{}{}
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
return dictionary
}
func main() {
words := search(
[]string{"p", "i", "", "", ""},
[][]string{nil, nil, {"t"}, nil, {"t"}},
[]string{"t"},
[]string{"o"},
)
for _, m := range words {
fmt.Println(m)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment