Module: Crucigrama::Crossword::WordQuery

Included in:
Crucigrama::Crossword
Defined in:
lib/crucigrama/crossword/word_query.rb

Overview

This module provides methods to query word existence, placement and search on a crossword

Instance Method Summary collapse

Instance Method Details

#black_positionsArray<Hash<Symbol,Integer>>



34
35
36
37
38
39
40
# File 'lib/crucigrama/crossword/word_query.rb', line 34

def black_positions
  @black_positions ||= lines(:horizontal).collect.with_index do |row, vertical_index|
    row.chars.collect.with_index do |cell, horizontal_index|
      cell == self.class::BLACK ? {:horizontal => horizontal_index, :vertical => vertical_index} : nil
    end.compact
  end.flatten
end

#can_set_word?(word, coordinates, direction) ⇒ Boolean



78
79
80
81
82
83
84
85
# File 'lib/crucigrama/crossword/word_query.rb', line 78

def can_set_word?(word, coordinates, direction)
  return false if out_of_bounds(word, coordinates, direction)
  return true if word.empty?
  other_direction = direction_other_than(direction)
  line = line(coordinates[other_direction], direction)
  regexp_str = line[coordinates[direction]..line.length][0..word.length-1].gsub(self.class::BLACK, '.')
  Regexp.new(regexp_str).match(word)
end

#word_at(coordinates, direction) ⇒ String?

Returns the word in the crossword at the given coordinates and direction, if there is one, or nil otherwise.

Options Hash (coordinates):

  • :horizontal (Integer)

    a number between 0 and the horizontal dimension of the crossword minus one specifying the row of the cell being queried

  • :vertical (Integer)

    a number between 0 and the vertical dimension of the crossword minus one specifying the column of the cell being queried



12
13
14
15
16
17
18
19
# File 'lib/crucigrama/crossword/word_query.rb', line 12

def word_at(coordinates, direction)
  other_direction = direction_other_than(direction)
  words.detect do |word|
    (word_positions[word][direction]||=[]).detect do |position|
      position[other_direction] == coordinates[other_direction] and position[direction] <= coordinates[direction] and position[direction] + word.length > coordinates[direction]
    end
  end
end

#word_at?(coordinates, direction, word) ⇒ Boolean

Returns if the word at the given coordinates and direction on the crossword is the given word.

Options Hash (coordinates):

  • :horizontal (Integer)

    a number between 0 and the horizontal dimension of the crossword minus one specifying the row of the cell being queried

  • :vertical (Integer)

    a number between 0 and the vertical dimension of the crossword minus one specifying the column of the cell being queried



29
30
31
# File 'lib/crucigrama/crossword/word_query.rb', line 29

def word_at?(coordinates, direction, word)
  word_at(coordinates, direction) == word
end

#word_positionsHash<String,Hash<Symbol, Array<Hash<Symbol, Integer>>>>



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/crucigrama/crossword/word_query.rb', line 53

def word_positions
  @word_positions ||= begin
    result = {}
    [:horizontal, :vertical].each do |direction|
      other_direction = direction_other_than(direction)
      lines(direction).each.with_index do |row, row_index|
        position = 0
        row.split(self.class::BLACK).each do |word|
          unless word.empty?
            result[word]||= {}
            result[word][direction]||= []
            result[word][direction] << {direction => position, other_direction=> row_index}
          end
          position+= word.length + 1
        end
      end
    end
    result
  end
end

#wordsArray<String>



43
44
45
# File 'lib/crucigrama/crossword/word_query.rb', line 43

def words
  word_positions.keys
end