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>>

Returns the list of black positions (or empty cells) in the crossword.

Returns:

  • (Array<Hash<Symbol,Integer>>)

    the list of black positions (or empty cells) in the crossword



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

Returns if the given word can be set on the crossword on the given coordinates and the given direction. The word can be set if it is not out of bounds on the crossword (that is, the cells it would occupy are defined) and if every crossword cell it would occupy either contains the corresponding word character or is a black position or empty cell.

Returns:

  • (Boolean)

    if the given word can be set on the crossword on the given coordinates and the given direction. The word can be set if it is not out of bounds on the crossword (that is, the cells it would occupy are defined) and if every crossword cell it would occupy either contains the corresponding word character or is a black position or empty cell.



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.

Parameters:

  • coordinates (Hash<Symbol,Integer>)

    the coordinates for the crossword cell being queried

  • direction (:horizontal, :vertical)

    the direction of the word being queried

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

Returns:

  • (String, nil)

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



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.

Parameters:

  • coordinates (Hash<Symbol,Integer>)

    the coordinates for the crossword cell being queried

  • direction (:horizontal, :vertical)

    the direction of the word being queried

  • word (String)

    the word that is or is not the word at the crossword

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

Returns:

  • (Boolean)

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



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>>>>

TODO:

reimplement using lines(direction)

Returns a relation of the words in the crosswords and their starting positions in both directions. Words are the primary key in the returned tree, followed by the direction (:horizontal or :vertical). The list of positions is given as an Array of hashes with values for the :horizontal and :vertical coordinates.

Returns:

  • (Hash<String,Hash<Symbol, Array<Hash<Symbol, Integer>>>>)

    a relation of the words in the crosswords and their starting positions in both directions. Words are the primary key in the returned tree, followed by the direction (:horizontal or :vertical). The list of positions is given as an Array of hashes with values for the :horizontal and :vertical coordinates



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>

Returns the list of words present in the crossword.

Returns:

  • (Array<String>)

    the list of words present in the crossword



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

def words
  word_positions.keys
end