Add some barely intelligent strategies
This commit is contained in:
parent
9595e62282
commit
269f16e837
7 changed files with 116 additions and 13 deletions
|
@ -4,7 +4,7 @@ require "webdrivers"
|
|||
|
||||
module Board
|
||||
class WordleUnlimited
|
||||
attr :guesses, :session
|
||||
attr :session
|
||||
|
||||
def initialize
|
||||
@guesses = []
|
||||
|
@ -50,6 +50,10 @@ module Board
|
|||
@session.quit
|
||||
end
|
||||
|
||||
def guesses
|
||||
locked_in.map { |row| row.text.tr("\n", "").downcase }
|
||||
end
|
||||
|
||||
def first_guess?
|
||||
guesses.empty?
|
||||
end
|
||||
|
@ -58,6 +62,21 @@ module Board
|
|||
session.find('div.feedback > div > b').text
|
||||
end
|
||||
|
||||
def template
|
||||
return Array.new(5, "*") unless locked_in.any?
|
||||
|
||||
locked_in
|
||||
.last
|
||||
.find_all('div.RowL-letter', wait: 0)
|
||||
.map do |letter|
|
||||
if letter.[]("class").split.include?("letter-correct")
|
||||
letter.text.downcase
|
||||
else
|
||||
"*"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def exact_letters
|
||||
|
@ -78,6 +97,10 @@ module Board
|
|||
session.has_text?(:visible, "Not a valid word", wait: 2)
|
||||
end
|
||||
|
||||
def locked_in
|
||||
session.find_all('div.RowL.RowL-locked-in', wait: 0) || []
|
||||
end
|
||||
|
||||
def click(key)
|
||||
session
|
||||
.find('div.Game-keyboard-button', text: /\A#{key}\Z/, wait: 0)
|
||||
|
|
|
@ -5,7 +5,10 @@ require_relative "outcome"
|
|||
require_relative "board/wordle_unlimited"
|
||||
require_relative "dictionary/dictionary"
|
||||
|
||||
require_relative "strategy/most_common"
|
||||
require_relative "strategy/naive"
|
||||
require_relative "strategy/template"
|
||||
require_relative "strategy/vowels"
|
||||
require_relative "strategy/wheel_of_fortune"
|
||||
|
||||
class Game
|
||||
|
@ -13,8 +16,8 @@ class Game
|
|||
def initialize(
|
||||
board: Board::WordleUnlimited,
|
||||
dictionary: Dictionary::Dictionary,
|
||||
start_strategy: Strategy::WheelOfFortune,
|
||||
strategy: Strategy::Naive
|
||||
start_strategy: Strategy::MostCommon,
|
||||
strategy: Strategy::Template
|
||||
)
|
||||
@board = board.new
|
||||
@dictionary = dictionary.new
|
||||
|
@ -35,6 +38,7 @@ class Game
|
|||
good_letters: board.allowed_letters,
|
||||
bad_letters: board.bad_letters,
|
||||
guesses: board.guesses,
|
||||
template: board.template,
|
||||
)
|
||||
|
||||
board.answer(guess)
|
||||
|
|
31
lib/strategy/most_common.rb
Normal file
31
lib/strategy/most_common.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
module Strategy
|
||||
class MostCommon
|
||||
attr :dictionary, :word_size
|
||||
|
||||
def initialize(dictionary:, word_size: 5)
|
||||
@dictionary = dictionary
|
||||
@word_size = word_size
|
||||
end
|
||||
|
||||
def guess(**args)
|
||||
dictionary.words
|
||||
.select { |word| word.length == word_size }
|
||||
.select { |word| (most_common_letters - word.chars).length == 0 }
|
||||
.sample
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def most_common_letters
|
||||
@most_common_letters ||= dictionary.words
|
||||
.select { |word| word.length == word_size }
|
||||
.map(&:chars)
|
||||
.flatten
|
||||
.tally
|
||||
.sort_by { |letter, count| count }
|
||||
.reverse
|
||||
.map(&:first)
|
||||
.first(5)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,16 +1,15 @@
|
|||
module Strategy
|
||||
class Naive
|
||||
WORD_SIZE = 5
|
||||
attr :dictionary, :word_size
|
||||
|
||||
attr :dictionary
|
||||
|
||||
def initialize(dictionary:)
|
||||
def initialize(dictionary:, word_size: 5)
|
||||
@dictionary = dictionary
|
||||
@word_size = word_size
|
||||
end
|
||||
|
||||
def guess(good_letters:, bad_letters:, **args)
|
||||
dictionary.words
|
||||
.select { |word| word.length == WORD_SIZE }
|
||||
.select { |word| word.length == word_size }
|
||||
.reject { |word| bad_letters.any? { |letter| word.chars.include?(letter) } }
|
||||
.select { |word| (good_letters - word.chars).length == 0 }
|
||||
.sample
|
||||
|
|
24
lib/strategy/template.rb
Normal file
24
lib/strategy/template.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
module Strategy
|
||||
class Template
|
||||
attr :dictionary, :word_size
|
||||
|
||||
def initialize(dictionary:, word_size: 5)
|
||||
@dictionary = dictionary
|
||||
@word_size = word_size
|
||||
end
|
||||
|
||||
def guess(good_letters:, bad_letters:, guesses:, template:, **args)
|
||||
dictionary.words
|
||||
.select { |word| word.length == word_size }
|
||||
.reject { |word| bad_letters.any? { |letter| word.chars.include?(letter) } }
|
||||
.select { |word| (good_letters - word.chars).length == 0 }
|
||||
.reject { |word| guesses.include?(word) }
|
||||
.select do |word|
|
||||
template.each_with_index.all? do |letter, index|
|
||||
letter == "*" || letter == word.chars[index]
|
||||
end
|
||||
end
|
||||
.sample
|
||||
end
|
||||
end
|
||||
end
|
23
lib/strategy/vowels.rb
Normal file
23
lib/strategy/vowels.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
module Strategy
|
||||
class Vowels
|
||||
attr :dictionary, :word_size
|
||||
|
||||
def initialize(dictionary:, word_size: 5)
|
||||
@dictionary = dictionary
|
||||
@word_size = word_size
|
||||
end
|
||||
|
||||
def guess(**args)
|
||||
dictionary.words
|
||||
.select { |word| word.length == word_size }
|
||||
.select { |word| (vowels - word.chars).length <= 2 }
|
||||
.sample
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def vowels
|
||||
%w(a e i o u y)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,16 +1,15 @@
|
|||
module Strategy
|
||||
class WheelOfFortune
|
||||
WORD_SIZE = 5
|
||||
attr :dictionary, :word_size
|
||||
|
||||
attr :dictionary
|
||||
|
||||
def initialize(dictionary:)
|
||||
def initialize(dictionary:, word_size: 5)
|
||||
@dictionary = dictionary
|
||||
@word_size = word_size
|
||||
end
|
||||
|
||||
def guess(**args)
|
||||
dictionary.words
|
||||
.select { |word| word.length == WORD_SIZE }
|
||||
.select { |word| word.length == word_size }
|
||||
.select { |word| (start_letters - word.chars).length == 1 }
|
||||
.sample
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue