Sha256: 03e57242aba3892e44b4f8b94fb62025386dd73e58d7aed9f03fd73d12df60bf

Contents?: true

Size: 1.78 KB

Versions: 6

Compression:

Stored size: 1.78 KB

Contents

# frozen_string_literal: true

module Codebreaker
  # Matching mechanism to determine the number
  # of bulls and cows in the guess.
  class Matcher
    attr_reader :marker, :secret_code_hash
    attr_reader :exact_matches, :all_matches, :bulls, :cows
    def initialize(marker = Markers::PlusMinusMarker.new)
      @marker = marker
      @secret_code_hash = hash_with_default_array_value
    end

    def secret_code=(secret_code)
      @secret_code_hash = array_to_hash_of_positions(unify_code(secret_code))
    end

    def match?(guess)
      match(array_to_hash_of_positions(unify_code(guess)))

      bulls == 4
    end

    def marks
      marker.mark(bulls, cows)
    end

    private

    def unify_code(code)
      code.is_a?(String) ? code.split('') : code
    end

    def array_to_hash_of_positions(array)
      array
        .each_with_object(hash_with_default_array_value)
        .with_index do |(digit, hash), position|
          hash[digit].push(position)
          hash
        end
    end

    def hash_with_default_array_value
      Hash.new { |h, digit| h[digit] = [] }
    end

    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

    def digit_is_not_present_in_the_secret_code(digit)
      secret_code_hash[digit].empty?
    end

    def add_exact_matches(digit, positions)
      @exact_matches += (secret_code_hash[digit] & positions).size
    end

    def add_all_matches(digit, positions)
      @all_matches += [secret_code_hash[digit], positions].min_by(&:size).size
    end
  end
end

Version data entries

6 entries across 6 versions & 1 rubygems

Version Path
codebreaker_mats-0.1.6 lib/codebreaker_mats/matcher.rb
codebreaker_mats-0.1.5 lib/codebreaker_mats/matcher.rb
codebreaker_mats-0.1.4 lib/codebreaker_mats/matcher.rb
codebreaker_mats-0.1.3 lib/codebreaker_mats/matcher.rb
codebreaker_mats-0.1.2 lib/codebreaker_mats/matcher.rb
codebreaker_mats-0.1.1 lib/codebreaker_mats/matcher.rb