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