Skip to content

Instantly share code, notes, and snippets.

@leklund
Created September 8, 2022 19:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leklund/2f0516014ea64551a07fe53dada74e75 to your computer and use it in GitHub Desktop.
Save leklund/2f0516014ea64551a07fe53dada74e75 to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"sort"
"strconv"
"strings"
"time"
)
type Hive struct {
chars []rune
words []string
panagrams []string
}
type Config struct {
sets int
minP int
maxP int
minW int
maxW int
words []string
}
var Alphabet = []rune{'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 main() {
conf := &Config{}
reader := bufio.NewReader(os.Stdin)
fmt.Printf("How many letter sets to find: ")
res, err := reader.ReadString('\n')
if err != nil {
panic(err)
}
conf.sets, err = strconv.Atoi(strings.TrimRight(res, "\n"))
if err != nil {
panic(err)
}
fmt.Printf("Mininum number of panagrams: ")
res, err = reader.ReadString('\n')
if err != nil {
panic(err)
}
conf.minP, err = strconv.Atoi(strings.TrimRight(res, "\n"))
fmt.Printf("Maximum number of panagrams: ")
res, err = reader.ReadString('\n')
if err != nil {
panic(err)
}
conf.maxP, err = strconv.Atoi(strings.TrimRight(res, "\n"))
fmt.Printf("Mininum number of words: ")
res, err = reader.ReadString('\n')
if err != nil {
panic(err)
}
conf.minW, err = strconv.Atoi(strings.TrimRight(res, "\n"))
fmt.Printf("Maximum number of words: ")
res, err = reader.ReadString('\n')
if err != nil {
panic(err)
}
conf.maxW, err = strconv.Atoi(strings.TrimRight(res, "\n"))
conf.words = WordsFromFile("./2of12inf.txt")
hives := FindSets(conf)
for _, h := range hives {
fmt.Println("letters: ", sortLetters(h.chars))
fmt.Println("panagrams: ", h.panagrams)
fmt.Println("words: ", len(h.words))
}
}
func FindSets(c *Config) []Hive {
var hives []Hive
for {
chars := RandoLetters()
charMap := make(map[rune]interface{})
for _, ch := range chars {
charMap[ch] = struct{}{}
}
requiredLetter := chars[0]
h := Hive{
chars: chars,
}
for _, word := range c.words {
okay, panagram := checkWord(word, requiredLetter, charMap)
if okay {
if panagram {
h.panagrams = append(h.panagrams, word)
} else {
h.words = append(h.words, word)
}
}
if len(h.panagrams) > c.maxP || len(h.words) > c.maxW {
break
}
}
if len(h.panagrams) >= c.minP && len(h.panagrams) <= c.maxP && len(h.words) >= c.minW && len(h.words) <= c.maxW {
hives = append(hives, h)
}
if len(hives) == c.sets {
return hives
}
}
}
func WordsFromFile(path string) []string {
file, err := os.Open(path)
defer file.Close()
if err != nil {
panic(err)
}
var words []string
s := bufio.NewScanner(file)
s.Split(bufio.ScanLines)
for s.Scan() {
word := s.Text()
if len(word) < 4 {
continue
}
words = append(words, word)
}
return words
}
func RandoLetters() []rune {
for {
var ltrs []rune
var vc int
rand.Seed(time.Now().UnixNano())
p := rand.Perm(26)
for _, r := range p[:7] {
if isVowel(Alphabet[r]) {
vc++
}
ltrs = append(ltrs, Alphabet[r])
}
if vc > 1 {
return ltrs
}
}
}
func checkWord(word string, req rune, charMap map[rune]interface{}) (bool, bool) {
hasReq := false
seen := make(map[rune]interface{})
for _, ch := range word {
if ch == req {
hasReq = true
}
if _, ok := charMap[ch]; !ok {
return false, false
} else {
seen[ch] = struct{}{}
}
}
if len(seen) == 7 {
return hasReq, true
} else {
return hasReq, false
}
}
func isVowel(c rune) bool {
return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'y'
}
func sortLetters(ltrs []rune) string {
// pop
req, ltrs := ltrs[0], ltrs[1:]
sort.Slice(ltrs, func(i, j int) bool {
return ltrs[i] < ltrs[j]
})
//unshift
ltrs = append([]rune{req}, ltrs...)
return string(ltrs)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment