浏览代码

feat: simulator prototype

Alex White 5 月之前
父节点
当前提交
a700eb9ba1
共有 4 个文件被更改,包括 242 次插入7 次删除
  1. 21 7
      fallout.go
  2. 38 0
      games.txt
  3. 143 0
      simulator.go
  4. 40 0
      simulator_test.go

+ 21 - 7
fallout.go

@@ -16,17 +16,24 @@ func main() {
 		os.Exit(1)
 	}
 
-	err = game.scoreWordsByCommonLetterLocations()
+	simulator := NewSimulator(*game)
+	err = simulator.SimulateAllPossibleGames()
 	if err != nil {
-		fmt.Printf("Error scoring Words: %s\n", err)
+		fmt.Printf("Error simulating all possible games: %s\n", err)
 		os.Exit(1)
 	}
 
-	_, err = game.printSortedScores()
-	if err != nil {
-		fmt.Printf("Error printing sorted scores: %s\n", err)
-		os.Exit(1)
-	}
+	//err = game.scoreWordsByCommonLetterLocations()
+	//if err != nil {
+	//	fmt.Printf("Error scoring Words: %s\n", err)
+	//	os.Exit(1)
+	//}
+	//
+	//_, err = game.printSortedScores()
+	//if err != nil {
+	//	fmt.Printf("Error printing sorted scores: %s\n", err)
+	//	os.Exit(1)
+	//}
 
 	for i := 0; i < 3; i++ {
 		guess, score := getGuessAndScoreFromStdin()
@@ -46,6 +53,13 @@ func main() {
 			os.Exit(1)
 		}
 
+		bestGuess, err := game.getBestGuess()
+		if err != nil {
+			fmt.Printf("Error getting best guess: %s\n", err)
+			os.Exit(1)
+		}
+		fmt.Sprintf("Best Guess: %s", bestGuess)
+
 		if len(game.Words) == 1 {
 			for word := range game.Words {
 				fmt.Printf("The word is: %s\n", word)

+ 38 - 0
games.txt

@@ -52,3 +52,41 @@ hands
 range
 
 
+lending
+sealing
+element
+enclave
+sparing
+decline
+recruit
+dealing *
+feeling
+require
+ceiling
+lecture
+sealant
+setting
+believe
+servant
+defeats
+leading
+decrees
+
+guides
+posted
+former
+become
+armory
+border
+member *
+wishes
+priced
+fended
+depart
+mutter
+serves
+cellar
+murder
+nomads
+series
+proper

+ 143 - 0
simulator.go

@@ -0,0 +1,143 @@
+package main
+
+import (
+	"fmt"
+	"os"
+)
+
+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() error {
+
+	bestGuessLossCount := 99
+	bestGuessTotalRounds := 99
+
+	wordLossCounts := make(map[string]int)
+	totalRounds := make(map[string]int)
+
+	for initialWord := range s.Game.Words {
+		fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
+		lossCount, totalRoundCount := s.SimulateOneGame(initialWord)
+		wordLossCounts[initialWord] = lossCount
+		totalRounds[initialWord] = totalRoundCount
+		if lossCount < bestGuessLossCount {
+			bestGuessLossCount = lossCount
+			bestGuessTotalRounds = totalRoundCount
+		} else if lossCount == bestGuessLossCount && totalRoundCount < bestGuessTotalRounds {
+			bestGuessTotalRounds = totalRoundCount
+		}
+	}
+
+	fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
+
+	err := s.Game.scoreWordsByCommonLetterLocations()
+	if err != nil {
+		return fmt.Errorf("Error scoring Words: %s", err)
+	}
+	for _, word := range s.Game.getSortedScores() {
+		if wordLossCounts[word] == bestGuessLossCount && totalRounds[word] == bestGuessTotalRounds {
+			fmt.Printf("\nBest Guess: %s  Failed Branches: %d  Total Rounds: %d\n\n", word, bestGuessLossCount, totalRounds[word])
+			break
+		}
+	}
+
+	return nil
+}
+
+func (s Simulation) SimulateOneGame(initialWord string) (int, int) {
+
+	lossCount := 0
+	totalRounds := 0
+	maxRounds := 4
+
+ANSWER_LOOP:
+	for answer := range s.Game.Words {
+
+		simulatedGame := NewGame()
+		simulatedGame.Words = make(map[string]*Word)
+		for word := range s.Game.Words {
+			simulatedGame.Words[word] = &Word{Word: word}
+		}
+
+		guess := initialWord
+
+		for guessRounds := 1; guessRounds <= maxRounds; guessRounds++ {
+
+			totalRounds++
+
+			if guess == answer {
+				fmt.Printf("Rounds: %d  Initial Word: %s  Target Word: %s\n", guessRounds, initialWord, answer)
+				if guessRounds > maxRounds {
+					lossCount++
+				}
+				continue ANSWER_LOOP
+			}
+
+			score := s.getScore(guess, answer)
+			//fmt.Printf("Score: %d\n", score)
+
+			simulatedGame.FilterWords(guess, score)
+			//fmt.Printf("Words remaining: %+v\n", simulatedGame.Words)
+
+			err := simulatedGame.scoreWordsByCommonLetterLocations()
+			if err != nil {
+				fmt.Printf("Error scoring Words: %s\n", err)
+				os.Exit(1)
+			}
+
+			if len(simulatedGame.Words) == 1 {
+				//fmt.Printf("The word is: %s\n", guess)
+				for word := range simulatedGame.Words {
+
+					if word != answer {
+						fmt.Printf("Incorrectly guessed word: %s => This should never happen!\n", word)
+						os.Exit(1)
+					}
+
+					if guessRounds > maxRounds {
+						lossCount++
+					}
+
+					fmt.Printf("Rounds: %d  Initial Word: %s  Target Word: %s\n", guessRounds, initialWord, answer)
+					continue ANSWER_LOOP
+				}
+			} else {
+				//fmt.Printf("Number of words remaining: %d\n", len(simulatedGame.Words))
+			}
+
+			guess, err = simulatedGame.getBestGuess()
+			if err != nil {
+				fmt.Printf("Error calculating best guess: %s\n", err)
+				os.Exit(1)
+			}
+		}
+	}
+	fmt.Printf("\nInitial Word: %s  Loss Count: %d  Total Rounds: %d\n", initialWord, lossCount, totalRounds)
+
+	return lossCount, totalRounds
+}
+
+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
+}

+ 40 - 0
simulator_test.go

@@ -0,0 +1,40 @@
+package main
+
+import (
+	"fmt"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+func TestSimulation_Run(t *testing.T) {
+	type fields struct {
+		Game *Game
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		wantErr assert.ErrorAssertionFunc
+	}{
+		{
+			name: "simple words",
+			fields: fields{
+				Game: &Game{
+					Words: map[string]*Word{
+						"aaa": {Word: "aaa"},
+						"aab": {Word: "aab"},
+						"abb": {Word: "abb"},
+					},
+				},
+			},
+			wantErr: assert.NoError,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := Simulation{
+				Game: tt.fields.Game,
+			}
+			tt.wantErr(t, s.SimulateAllPossibleGames(), fmt.Sprintf("SimulateAllPossibleGames()"))
+		})
+	}
+}