class Codebreaker::Matcher

Matching mechanism to determine the number of bulls and cows in the guess.

Attributes

marker[R]
secret_code_hash[R]

Public Class Methods

new(marker = Markers::PlusMinusMarker.new) click to toggle source
# File lib/codebreaker_mats/matcher.rb, line 8
def initialize(marker = Markers::PlusMinusMarker.new)
  @marker = marker
end

Public Instance Methods

marks() click to toggle source
# File lib/codebreaker_mats/matcher.rb, line 22
def marks
  marker.mark(@bulls, @cows)
end
match?(guess) click to toggle source
# File lib/codebreaker_mats/matcher.rb, line 16
def match?(guess)
  match(array_to_hash_of_positions(unify_code(guess)))

  @bulls == 4
end
secret_code=(secret_code) click to toggle source
# File lib/codebreaker_mats/matcher.rb, line 12
def secret_code=(secret_code)
  @secret_code_hash = array_to_hash_of_positions(unify_code(secret_code))
end

Private Instance Methods

add_all_matches(digit, positions) click to toggle source
# File lib/codebreaker_mats/matcher.rb, line 65
def add_all_matches(digit, positions)
  @all_matches += [secret_code_hash[digit], positions].min_by(&:size).size
end
add_exact_matches(digit, positions) click to toggle source
# File lib/codebreaker_mats/matcher.rb, line 61
def add_exact_matches(digit, positions)
  @exact_matches += (secret_code_hash[digit] & positions).size
end
array_to_hash_of_positions(array) click to toggle source
# File lib/codebreaker_mats/matcher.rb, line 32
def array_to_hash_of_positions(array)
  array
    .each_with_object({})
    .with_index do |(digit, hash), position|
      hash[digit] ||= []
      hash[digit].push(position)
      hash
    end
end
digit_is_not_present_in_the_secret_code(digit) click to toggle source
# File lib/codebreaker_mats/matcher.rb, line 57
def digit_is_not_present_in_the_secret_code(digit)
  secret_code_hash[digit] == nil
end
match(guess_hash) click to toggle source
# File lib/codebreaker_mats/matcher.rb, line 42
def match(guess_hash)
  @exact_matches = 0
  @all_matches = 0

  guess_hash.each do |digit, positions|
    next if digit_is_not_present_in_the_secret_code(digit)

    add_exact_matches(digit, positions)
    add_all_matches(digit, positions)
  end

  @bulls = @exact_matches
  @cows = @all_matches - @exact_matches
end
unify_code(code) click to toggle source
# File lib/codebreaker_mats/matcher.rb, line 28
def unify_code(code)
  code.is_a?(String) ? code.split('') : code
end