package main import ( "fmt" "slices" ) type Simulation struct { Game *Game BestGuess string BestGuessRounds int SuccessCount int FailCount int TotalRounds int } func NewSimulator(g Game) *Simulation { return &Simulation{ Game: &g, } } func (s Simulation) SimulateAllPossibleGames() (string, error) { bestGuessLossCount := 99 bestGuessMaxRounds := 99 bestGuessTotalRounds := 99 wordLossCounts := make(map[string]int) totRoundCounts := make(map[string]int) maxRoundCounts := make(map[string]int) var words []string for word := range s.Game.Words { words = append(words, word) } slices.Sort(words) for _, initialWord := range words { fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>") simulatedGame := NewGame() simulatedGame.Words = make(map[string]*Word) for word := range s.Game.Words { simulatedGame.Words[word] = &Word{Word: word} } lossCount, maxRounds, totalRounds := s.SimulateOneInitialWord(simulatedGame, initialWord) wordLossCounts[initialWord] = lossCount totRoundCounts[initialWord] = totalRounds maxRoundCounts[initialWord] = maxRounds //fmt.Printf("Initial Word: %s Loss Count: %d Max Rounds: %d Total Rounds: %d\n", initialWord, lossCount, maxRounds, totalRounds) if lossCount < bestGuessLossCount { bestGuessLossCount = lossCount bestGuessTotalRounds = totalRounds bestGuessMaxRounds = maxRounds } else if lossCount == bestGuessLossCount && maxRounds < bestGuessMaxRounds { bestGuessTotalRounds = totalRounds bestGuessMaxRounds = maxRounds } else if lossCount == bestGuessLossCount && maxRounds == bestGuessMaxRounds && totalRounds < bestGuessTotalRounds { bestGuessTotalRounds = totalRounds } } fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>") fmt.Print("Simulation completed\n\n") s.Game.scoreWordsByCommonLetterLocations() var bestGuess string for _, word := range s.Game.getSortedScores() { if wordLossCounts[word] == bestGuessLossCount && totRoundCounts[word] == bestGuessTotalRounds && maxRoundCounts[word] == bestGuessMaxRounds { fmt.Printf("Best Guess: %s Failed Branches: %d Total Rounds: %d Max Rounds: %d\n\n", word, bestGuessLossCount, bestGuessTotalRounds, bestGuessMaxRounds) bestGuess = word break } } return bestGuess, nil } func (s Simulation) SimulateOneInitialWord(game *Game, initialWord string) (lossCount, maxRounds, totalRounds int) { debugPrint("Initial Word: %s\n", initialWord) for answer := range s.Game.Words { debugPrint(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n") debugPrint("Target Word: %s\n", answer) simulatedGame := NewGame() simulatedGame.Words = make(map[string]*Word) for word := range game.Words { simulatedGame.Words[word] = &Word{Word: word} } won, rounds := s.SimulateOneGame(simulatedGame, initialWord, answer) if !won { lossCount++ } totalRounds += rounds if rounds > maxRounds { maxRounds = rounds } } fmt.Printf("Summary: Initial Word: %s Loss Count: %d Max Rounds: %d Total Rounds: %d\n", initialWord, lossCount, maxRounds, totalRounds) return lossCount, maxRounds, totalRounds } func (s Simulation) SimulateOneGame(simulatedGame *Game, initialWord, answer string) (bool, int) { if initialWord == answer { fmt.Printf(" Win in 1 round => %s .. %s\n", initialWord, answer) return true, 1 } guess := initialWord // 10 rounds max just to prevent infinite loops var round int for round = 1; round <= 10; round++ { if len(simulatedGame.Words) == 1 { debugPrint("Only one guess remaining after filtering: %s\n", guess) break } if round == 1 { debugPrint("First guess, initial Word: %s\n", initialWord) } else { guess = simulatedGame.getBestGuess() debugPrint("Round %d, guess: %s\n", round, guess) } if guess == answer { break } score := s.getScore(guess, answer) debugPrint("guess '%s' matches %d locations in answer '%s'\n", guess, score, answer) simulatedGame.FilterWords(guess, score) debugPrint("Words remaining after filtering: %+v\n", simulatedGame.Words) simulatedGame.scoreWordsByCommonLetterLocations() debugPrint("End round %d, not solved, %d words remaining\n", round, len(simulatedGame.Words)) } if round > 4 { fmt.Printf(" Loss in %d rounds => %s .. %s\n", round, initialWord, answer) return false, round } fmt.Printf(" Win in %d rounds => %s .. %s\n", round, initialWord, answer) return true, round } func (s Simulation) getScore(guess string, answer string) int { score := 0 for idx, letter := range answer { if string(letter) == string(guess[idx]) { score++ } } return score }