I am a novice coder and I am very new to algorithms. Something about my code leads me to believe that it is unnecessarily verbose and/or inefficient. I am building a command line Mastermind game, and part of the project is to provide feedback for a user's guess. In the game, the codemaker creates a secret code with four "pegs" of any of the six predefined colors.
The codebreaker has 12 chances to guess the correct code while gradually improving their guess with the help of feedback from the codemaker each time. The feedback consists of four "key pegs", which must be either black or white.
The codemaker puts down a black peg to indicate that the player chose the correct position and the correct color. A white key peg indicates that the user selected a color that exists in the secret code but is in the wrong position.
However, only one white peg is put down for each correct color guess, even if there is many of that color in the secret code.
For example, if:
secret_code = ["Red", "Blue", "Green", "Red"]
guess = ["Blue", "Green", "Red", "Red"],
#=> feedback is ["White, "White", "Black", "White"] in any order
Here is another example:
secret_code = ["Red", "Blue", "Red", "Red"]
guess = ["Blue", "Red", "Green", "Green"]
p computer.provide_feedback(secret_code, guess)
#=> ["White", "White", " ", " "]
The first step of my code is to turn the two arrays into hashes with the colors as values and an array of their indices as the values. This way I can compare the frequency and position of each color in each array.
The next step is to iterate through the guess hash, and for each iteration create an intersection array that contains the elements that exist in both. The number of intersected elements determines the number of black pegs to be placed into the feedback array.
To find the number of white pegs, the program checks if the array for the color indices in the guess array is less in size than the secret_code indices to avoid counting more of that color than is in the secret_code. Then the program finds the number of elements left over that aren't intersected, and that determines the number of white pegs.
Here is the code for this specific portion of my game:
def provide_feedback(secret_code, guess)
secret_indices = hash_of_indices(secret_code)
guess_indices = hash_of_indices(guess)
feedback = format_feedback(calculate_feedback(secret_indices, guess_indices))
feedback
end
def hash_of_indices(array)
array.each_with_index.inject(Hash.new {Array.new}) do |hash, (elem, i)|
hash[elem] += [i]
hash
end
end
def calculate_feedback(secret_hash, guess_hash)
feedback = []
black = "Black"
white = "White"
guess_hash.each do |k, v|
intersection = (v & secret_hash[k])
intersection.length.times { feedback << black }
if v.length <= secret_hash[k].length
(v.length - intersection.length).times { feedback << white }
end
end
feedback
end
def format_feedback(feedback)
formatted = feedback
formatted << " " until formatted.length == 4
formatted
end