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