1
0
Fork 0

Add some barely intelligent strategies

This commit is contained in:
Andrew Tomaka 2022-01-27 20:52:13 -05:00
parent 9595e62282
commit 269f16e837
Signed by: atomaka
GPG key ID: 61209BF70A5B18BE
7 changed files with 116 additions and 13 deletions

View file

@ -4,7 +4,7 @@ require "webdrivers"
module Board module Board
class WordleUnlimited class WordleUnlimited
attr :guesses, :session attr :session
def initialize def initialize
@guesses = [] @guesses = []
@ -50,6 +50,10 @@ module Board
@session.quit @session.quit
end end
def guesses
locked_in.map { |row| row.text.tr("\n", "").downcase }
end
def first_guess? def first_guess?
guesses.empty? guesses.empty?
end end
@ -58,6 +62,21 @@ module Board
session.find('div.feedback > div > b').text session.find('div.feedback > div > b').text
end 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 private
def exact_letters def exact_letters
@ -78,6 +97,10 @@ module Board
session.has_text?(:visible, "Not a valid word", wait: 2) session.has_text?(:visible, "Not a valid word", wait: 2)
end end
def locked_in
session.find_all('div.RowL.RowL-locked-in', wait: 0) || []
end
def click(key) def click(key)
session session
.find('div.Game-keyboard-button', text: /\A#{key}\Z/, wait: 0) .find('div.Game-keyboard-button', text: /\A#{key}\Z/, wait: 0)

View file

@ -5,7 +5,10 @@ require_relative "outcome"
require_relative "board/wordle_unlimited" require_relative "board/wordle_unlimited"
require_relative "dictionary/dictionary" require_relative "dictionary/dictionary"
require_relative "strategy/most_common"
require_relative "strategy/naive" require_relative "strategy/naive"
require_relative "strategy/template"
require_relative "strategy/vowels"
require_relative "strategy/wheel_of_fortune" require_relative "strategy/wheel_of_fortune"
class Game class Game
@ -13,8 +16,8 @@ class Game
def initialize( def initialize(
board: Board::WordleUnlimited, board: Board::WordleUnlimited,
dictionary: Dictionary::Dictionary, dictionary: Dictionary::Dictionary,
start_strategy: Strategy::WheelOfFortune, start_strategy: Strategy::MostCommon,
strategy: Strategy::Naive strategy: Strategy::Template
) )
@board = board.new @board = board.new
@dictionary = dictionary.new @dictionary = dictionary.new
@ -35,6 +38,7 @@ class Game
good_letters: board.allowed_letters, good_letters: board.allowed_letters,
bad_letters: board.bad_letters, bad_letters: board.bad_letters,
guesses: board.guesses, guesses: board.guesses,
template: board.template,
) )
board.answer(guess) board.answer(guess)

View 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

View file

@ -1,16 +1,15 @@
module Strategy module Strategy
class Naive class Naive
WORD_SIZE = 5 attr :dictionary, :word_size
attr :dictionary def initialize(dictionary:, word_size: 5)
def initialize(dictionary:)
@dictionary = dictionary @dictionary = dictionary
@word_size = word_size
end end
def guess(good_letters:, bad_letters:, **args) def guess(good_letters:, bad_letters:, **args)
dictionary.words dictionary.words
.select { |word| word.length == WORD_SIZE } .select { |word| word.length == word_size }
.reject { |word| bad_letters.any? { |letter| word.chars.include?(letter) } } .reject { |word| bad_letters.any? { |letter| word.chars.include?(letter) } }
.select { |word| (good_letters - word.chars).length == 0 } .select { |word| (good_letters - word.chars).length == 0 }
.sample .sample

24
lib/strategy/template.rb Normal file
View 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
View 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

View file

@ -1,16 +1,15 @@
module Strategy module Strategy
class WheelOfFortune class WheelOfFortune
WORD_SIZE = 5 attr :dictionary, :word_size
attr :dictionary def initialize(dictionary:, word_size: 5)
def initialize(dictionary:)
@dictionary = dictionary @dictionary = dictionary
@word_size = word_size
end end
def guess(**args) def guess(**args)
dictionary.words dictionary.words
.select { |word| word.length == WORD_SIZE } .select { |word| word.length == word_size }
.select { |word| (start_letters - word.chars).length == 1 } .select { |word| (start_letters - word.chars).length == 1 }
.sample .sample
end end