class WordSearch::Solver

Attributes

benchmark[RW]
failed[RW]
plane[RW]
plane_file[RW]
script[RW]
word_bank[RW]
word_list_file[RW]

Public Class Methods

new(script, word_list_file, plane_file) click to toggle source
# File lib/word_search/solver.rb, line 8
def initialize(script, word_list_file, plane_file)
  @script         = script
  @word_list_file = word_list_file
  @word_bank      = WordBank.new(word_list_file)
  @plane_file     = plane_file
  @plane          = Plane.make_from_file(plane_file, should_catalog: false)
  @failed         = false
end

Public Instance Methods

perform() click to toggle source
# File lib/word_search/solver.rb, line 17
def perform
  return if script.blank?
  bm = benchmark_solution

  return(@benchmark = bm) if !failed && solved?

  "Word Search incorrectly solved"
end
solved?() click to toggle source
# File lib/word_search/solver.rb, line 26
def solved?
  @word_bank.all? do |word|
    correctly_found?(word, users_solution[word])
  end && proper_direction?
end

Private Instance Methods

benchmark_solution() click to toggle source
# File lib/word_search/solver.rb, line 34
def benchmark_solution
  Benchmark.measure do
    begin
      users_solution
    rescue
      self.failed = true
    end
  end
end
correctly_found?(word, positions) click to toggle source
# File lib/word_search/solver.rb, line 50
def correctly_found?(word, positions)
  word.split("").map.with_index do |letter, index|
    plane.letter_at(*positions[index]).letter == letter
  end.inject(:&)
end
import_solutions(solution_array) click to toggle source
# File lib/word_search/solver.rb, line 77
def import_solutions(solution_array)
  solution_array.split("---").map do |positions|
    {
      positions.strip.split("\n").map(&:first).join =>
        positions.strip.split("\n").map.with_index do |letter, index|
          [index, JSON.parse(letter[2..-1])]
        end.to_h
    }
  end.reduce({}, :merge)
end
proper_direction?() click to toggle source
# File lib/word_search/solver.rb, line 56
def proper_direction?
  users_solution.all? do |word, positions|
    values = positions.values
    direction = reduce_direction(values.pop.zip(*values), word)
    plane.directions.values.include?(direction)
  end
end
reduce_direction(values, word) click to toggle source
# File lib/word_search/solver.rb, line 64
def reduce_direction(values, word)
  values.map do |direction|
    gcd = direction.reduce(:gcd)
    direction.map { |coord| coord / gcd }.uniq
  end.map do |direction|
    if (direction = direction.inject(:-)).gcd(word.length) == word.length
      direction / word.length
    else
      direction
    end
  end
end
users_solution() click to toggle source
# File lib/word_search/solver.rb, line 44
def users_solution
  @users_solution ||= import_solutions(File.read(JSON.parse(
    `ruby #{script} #{plane_file} #{word_list_file}`
  )))
end