Created
April 5, 2022 22:15
-
-
Save kpmcc/537e4f052131b02387b6285af7c02a24 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"errors" | |
"fmt" | |
"math/rand" | |
"os" | |
"strings" | |
) | |
func readGuess(r *bufio.Reader, expectedLen int) []string { | |
input, err := r.ReadString('\n') | |
if err != nil { | |
fmt.Println("An eror occured while reading input. Please try again", err) | |
} | |
// remove the delimiter from the input string | |
trimmed := strings.TrimSuffix(input, "\n") | |
split := strings.SplitN(trimmed, "", expectedLen) | |
return split | |
} | |
func validateGuessLen(guess []string, expectedLen int) bool { | |
if len(guess) < expectedLen { | |
fmt.Fprintf(os.Stderr, "Error: Not enough colors in guess\n") | |
return false | |
} | |
lastElementIndex := expectedLen - 1 | |
if len(guess[lastElementIndex]) != 1 { | |
fmt.Fprintf(os.Stderr, "Error: Too many colors in guess\n") | |
return false | |
} | |
return true | |
} | |
func getColorIndices(colors []string) map[string][]int { | |
colorIndices := make(map[string][]int) | |
for i := 0; i < len(colors); i++ { | |
c := colors[i] | |
colorIndices[c] = append(colorIndices[c], i) | |
} | |
return colorIndices | |
} | |
func remove(s []int, i int) []int { | |
// Remove the element at index i by replacing it with the last element | |
// in the slice, and then dropping the last element from the slice | |
// !! This does not preserve order of elements | |
s[i] = s[len(s)-1] | |
return s[:len(s)-1] | |
} | |
func in(s []int, e int) bool { | |
for i := 0; i < len(s); i++ { | |
v := s[i] | |
if e == v { | |
return true | |
} | |
} | |
return false | |
} | |
func checkGuess(guess []string, validColors map[string]bool, actual []string) (pins []string, correct bool, err error) { | |
var responsePins []string | |
for i := 0; i < len(guess); i++ { | |
c := guess[i] | |
if !validColors[c] { | |
return responsePins, false, errors.New("Received invalid color in guess: " + c + "\n") | |
} | |
} | |
if len(guess) != len(actual) { | |
return responsePins, false, errors.New("Mismatched lengths betwwen guess and actual\n") | |
} | |
unmatchedActual := make(map[string]int) | |
var unmatchedGuessIndices []int | |
for i := 0; i < len(guess); i++ { | |
gc := guess[i] | |
ac := actual[i] | |
if gc == ac { | |
responsePins = append(responsePins, "K") | |
} else { | |
unmatchedActual[ac]++ | |
unmatchedGuessIndices = append(unmatchedGuessIndices, i) | |
} | |
} | |
if len(unmatchedGuessIndices) == 0 { | |
return responsePins, true, nil | |
} else { | |
for gi := 0; gi < len(unmatchedGuessIndices); gi++ { | |
ugi := unmatchedGuessIndices[gi] | |
gc := guess[ugi] | |
n, exists := unmatchedActual[gc] | |
if exists && n > 0 { | |
responsePins = append(responsePins, "W") | |
unmatchedActual[gc]-- | |
} | |
} | |
return responsePins, false, nil | |
} | |
} | |
func main() { | |
// Setup | |
fmt.Println("---MASTERMIND---") | |
const guessLen = 4 | |
const numGuesses = 10 | |
validColors := []string{"R", "G", "B", "P", "O", "Y"} | |
validColorsMap := make(map[string]bool) | |
fmt.Print("Valid colors: ") | |
for _, c := range validColors { | |
validColorsMap[c] = true | |
fmt.Printf("%s ", c) | |
} | |
fmt.Println() | |
// Generate actual color list | |
var actual []string | |
for i := 0; i < guessLen; i++ { | |
colorIndex := rand.Int() % len(validColors) | |
actual = append(actual, validColors[colorIndex]) | |
} | |
fmt.Println("Guesses should be entered without spaces (be nice)") | |
fmt.Println("Example: RBGO") | |
fmt.Println() | |
fmt.Println("After each guess, pins will be shown for the guess") | |
fmt.Println("Black pins ('K') indicate a correct color in the correct location") | |
fmt.Println("White pins ('W') indicate a correct color not in the correct location") | |
fmt.Println("Example: [K W W] - Indicates one correct color and position, and two correct colors in the wrong positions") | |
fmt.Println() | |
reader := bufio.NewReader(os.Stdin) | |
for gn := 0; gn < numGuesses; gn++ { | |
fmt.Printf("%d tries remaining. Please enter your guess: ", numGuesses-gn) | |
guess := readGuess(reader, guessLen) | |
if validateGuessLen(guess, guessLen) { | |
pins, correct, err := checkGuess(guess, validColorsMap, actual) | |
if err != nil { | |
fmt.Println("Error during guess processing") | |
fmt.Print(err) | |
} | |
if correct { | |
fmt.Printf("CORRECT! ") | |
break | |
} else { | |
fmt.Printf("You Guessed: %v - Response is: %v\n\n", guess, pins) | |
} | |
} | |
} | |
fmt.Printf("The answer is %v\n", actual) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment