Module: Scrabble::Solver

Defined in:
lib/scrabble-solver/solver.rb

Class Method Summary collapse

Class Method Details

.word_file_name=(file_name) ⇒ Object

Set a new word file. Exit the program if the file does not exist.

If the file does exist, the cached word list is cleared out and the next time the word list is requested, the new list from the new file is returned and subsequently cached.



12
13
14
15
16
17
18
19
20
21
# File 'lib/scrabble-solver/solver.rb', line 12

def self.word_file_name= file_name
  if File.exists? file_name
    # Reset the word list
    @word_list      = nil
    @word_file_name = file_name
  else
    puts "The file name #{file_name} is not valid."
    exit
  end
end

.word_list ⇒ Object

Reads in the words.txt file and returns an array containing all of the words in that file.

Example:

Scrabble::Solver.word_list.each do |word|
puts word
end


31
32
33
34
35
36
37
38
39
40
41
# File 'lib/scrabble-solver/solver.rb', line 31

def self.word_list
  @word_list ||= File.open(@word_file_name) do |file|
    file.readlines.map do |line|
      line.chomp
    end.delete_if do |line|
      line.length < 2
    end
  end

  @word_list.clone
end

.words_for(letters, options = Hash.new(nil)) ⇒ Object

Gets an array of words that would fit the current board of Scrabble tiles.

Example:

Scrabble::Solver.words_for "there"
# => An array of words that the tiles t, h, e, r, e could make.

Scrabble::Solver.words_for "there?"
# => An array of words that the tiles t, h, e, r, e plus a blank tile
#    could make.


54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/scrabble-solver/solver.rb', line 54

def self.words_for letters, options = Hash.new(nil)
  letters  = letters.downcase.split(//)
  unknowns = letters.count "?"
  letters.delete "?"

  # Set a new word file if the option has been specified
  if options[:word_file]
    self.word_file_name = options[:word_file]
  end

  words = word_list.keep_if do |word|
    # Split the word into its letters.
    word = word.split(//)

    # Strip the letters that are in our hand from the word.
    letters.each do |letter|
      unless word.index(letter).nil?
        word.delete_at word.index(letter)
      end
    end

    # Only return the word if the remaining letters is equal to the number
    # of unknowns.
    word.length == unknowns
  end

  # Filter only words that start with a specific sequence.
  if options[:starts_with]
    words.keep_if { |word| word.start_with? options[:starts_with] }
  end

  # Filter words that only end in a certain sequence.
  if options[:ends_with]
    words.keep_if { |word| word.end_with? options[:ends_with] }
  end

  # Fitler only words shorter than a given amount.
  if options[:shorter_than]
    words.keep_if { |word| word.length < options[:shorter_than].to_i }
  end

  # Filter words only longer than a given amount.
  if options[:longer_than]
    words.keep_if { |word| word.length > options[:longer_than].to_i }
  end

  # Filter words that contain a specific sequence at a given 1-based index.
  if options[:contains]
    # Generate a regex to match against the string. This regex will replace
    # question marks with dots, so that they match any character. This
    # gives the user a lot of power with the --contains --at combo.
    regex  = ''
    regex += ('^' + ('.' * (options[:at].to_i - 1))) if options[:at]
    regex += options[:contains].gsub('?', '.')
    regex  = Regexp.new regex
    words.keep_if do |word|
      word =~ regex
    end
  end

  return words
end