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) }