wordle_decoder 0.1.2 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dca5b9fbafa87be192d4a5768b878564412854bdb8838e1e9ac55d1eb0244d4a
4
- data.tar.gz: b9ec7358da606b398da0f653fc62d4ac2c8f697fc91f6a43dcf478c77a7f68d2
3
+ metadata.gz: 61618c17d27aec3ae0fc68ea34e5f316d050d72e556e5ab7c972871649a3e4d2
4
+ data.tar.gz: 6545c2ad4fc4113a210b2b8e5809827327ef0830bfafaaf9f9aa141c0706df4f
5
5
  SHA512:
6
- metadata.gz: d2fb07120f3c105302ae4b251cd3f7df6a80be4ca5aadc81cae29410bf63137024c277c3c862337b4b10bf7e4bda9ad8901626f01de27309e9e189d8a22a172b
7
- data.tar.gz: 9f21c02dc2d567e2e613482181ffe0a24b6d5e8b567f99333e76cc346d161dd67376c69a8615afc611754467da375380fd4282094e68cb452610afe8d568eff2
6
+ metadata.gz: f03be54869ded6a7a8364e9ecc30c23f755ce093b30f8b92f6075774ea160962fe40fd190ecc8061e71752ed41d26b5f91fe5729809ba4920650500b1d0ab9e6
7
+ data.tar.gz: 440b20a14eba2632a58ab7f79a78075f2798420f695540e269fbdcb9590f00ae7a2d21e6ac5c5c3e26ad0ea3b365c60639eb637827100b64e72ffe9b3abfd808
data/.rubocop.yml CHANGED
@@ -1,5 +1,6 @@
1
1
  AllCops:
2
2
  TargetRubyVersion: 2.6
3
+ NewCops: enable
3
4
 
4
5
  Style/StringLiterals:
5
6
  Enabled: true
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.1.0] - 2022-02-22
3
+ ## [0.1.5] - 2022-03-20
4
4
 
5
- - Initial release
5
+ - Support high contrast mode - https://github.com/mattruzicka/wordle_decoder/issues/4
6
+ - Fix edge case where words were being falsey considered impossible when containing more than one of the same letter which is in the answer - https://github.com/mattruzicka/wordle_decoder/issues/3
7
+ - Found some old notes/TODOs I took while on a walk and forgot about [4201916](https://github.com/mattruzicka/wordle_decoder/commit/4201916b47f84ba7ee851db938b8dba36eb64236)
8
+
9
+ ## [0.1.4] - 2022-03-06
10
+
11
+ - Deal with weird input chars - https://github.com/mattruzicka/wordle_decoder/issues/2
12
+
13
+ ## [0.1.3] - 2022-03-05
14
+
15
+ - Support shortcode emojis - https://github.com/mattruzicka/wordle_decoder/pull/1
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- wordle_decoder (0.1.0)
4
+ wordle_decoder (0.1.5)
5
5
  cli-ui (~> 1.5)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -1,19 +1,36 @@
1
1
  # Wordle Decoder
2
2
 
3
- It guesses your guesses based on all those little 🟨, 🟩, and ⬛ emojis that we now love to share.
3
+ It guesses your guesses based on all those little square emojis that we now love to share.
4
4
 
5
- Given your Wordle share text, with some degree of confidence, the decoder will spit back the five-letter words it thinks you played.
5
+ Given your Wordle share, the decoder will spit back the five-letter words it thinks you played with some degree of confidence.
6
6
 
7
7
  ## Installation
8
8
 
9
+ Have Ruby 2.7 or later installed, then run the following at the command line:
10
+
9
11
  $ gem install wordle_decoder
10
12
 
11
13
  ## Usage
12
14
 
13
- After entering the below at the command line, you should be prompted to enter your Wordle share and the Wordle word of the day.
15
+ After installing the gem, run `wordle_decoder` at the command line like so:
14
16
 
15
17
  $ wordle_decoder
16
18
 
17
- ## Examples
19
+ You'll be prompted to share your wordle. Go ahead and paste in your wordle share text. The share text should look something like this:
20
+
21
+ ```
22
+ Wordle 258 3/6
23
+
24
+ ⬛⬛🟨⬛🟨
25
+ ⬛🟩🟩🟩⬛
26
+ 🟩🟩🟩🟩🟩
27
+ ```
28
+ You'll then be prompted to confirm the word of the day, or if it couldn't figure it out, you'll be asked for it. After that, it'll _try_ to guess your guesses.
29
+
30
+ ## Why?
31
+
32
+ I wasn't sure if something like this was possible and thought it'd be a fun project to build. It does a pretty good job, at least some of the time... I built an excuse to play Wordle.
33
+
34
+ Enjoy,
18
35
 
19
- TODO...
36
+ [@mattruzicka](https://twitter.com/mattruzicka)
data/Rakefile CHANGED
@@ -20,7 +20,7 @@ task default: %i[test rubocop]
20
20
  task :create_word_search_files do
21
21
  sorted_words = load_words_sorted_by_frequency
22
22
  most_common_words = sorted_words.pop(3_000)
23
- most_common_words, less_common_words = most_common_words.partition { |r| r.split("").uniq.count == 5 }
23
+ most_common_words, less_common_words = most_common_words.partition { |r| r.chars.uniq.count == 5 }
24
24
  File.write(lib_path("most_common_words.txt"), most_common_words.join("\n"))
25
25
  File.write(lib_path("less_common_words.txt"), less_common_words.join("\n"))
26
26
  File.write(lib_path("least_common_words.txt"), sorted_words.join("\n"))
@@ -29,7 +29,7 @@ end
29
29
  task :output_most_common_letters do
30
30
  words = load_wordle_words("allowed_answers.txt")
31
31
  words.concat load_wordle_words("allowed_guesses.txt")
32
- letter_count_tally = words.flat_map { _1.split("") }.tally
32
+ letter_count_tally = words.flat_map { _1.chars }.tally
33
33
  letter_count_tally = letter_count_tally.sort_by { -_2 }
34
34
  puts letter_count_tally.first(10).map { _1.first }.join(" ")
35
35
  end
data/bin/wordle_decoder CHANGED
@@ -134,9 +134,12 @@ salutations = ["Maybe some of those are your words!",
134
134
  "What lovely words you have!",
135
135
  "I hope my words were as good as yours!",
136
136
  "Please enjoy the rest of your day!",
137
+ "I hope that what I'm lacking in precision is made up in personality.",
138
+ "I see your love of the game.",
139
+ "Wanna exchange five letter words?",
137
140
  "I may not be positive about your words, but I am about you!",
138
141
  "Thank you for spending time with me!",
139
142
  "I enjoyed our time together!"].freeze
140
143
 
141
144
  puts CLI::UI.fmt("\n\n #{salutations.sample}\n " \
142
- "{{blue:https://github.com/mattruzicka/wordle_decoder}}}}\n\n")
145
+ "{{blue:https://github.com/mattruzicka/wordle_decoder}}}}\n\n")
@@ -9,19 +9,19 @@ class WordleDecoder
9
9
  end
10
10
 
11
11
  def score
12
- @score ||= words_with_scores.sum(&:last)
12
+ @score ||= best_words_with_scores.sum(&:last)
13
13
  end
14
14
 
15
15
  def word_scores
16
- @word_scores ||= words_with_scores.map(&:last)
16
+ @word_scores ||= best_words_with_scores.map(&:last)
17
17
  end
18
18
 
19
19
  def words
20
- @words ||= words_with_scores.map { |w, _s| w.to_s }
20
+ @words ||= best_words_with_scores.map { |w, _s| w.to_s }
21
21
  end
22
22
 
23
- def words_with_scores
24
- @words_with_scores ||= select_words_with_scores
23
+ def best_words_with_scores
24
+ @best_words_with_scores ||= select_best_words_with_scores
25
25
  end
26
26
 
27
27
  def inspect
@@ -30,18 +30,7 @@ class WordleDecoder
30
30
 
31
31
  private
32
32
 
33
- #
34
- # Greatly penalize words that have multiple of the same black letters
35
- # Greatly penalize words that have the same black letters as any seen word
36
- # Greatly penalize words that have the same yellow letter/index pair as any seen word
37
- # Reward words that have yellow letters that match yellow letters in seen words, but in different positions
38
- # Reward words that have yellow letters that match green letters in seen words
39
- # Penalize words that have yellow letters that don't appear in seen words
40
- # Penalize words that have green letters that don't appear in seen words
41
- # Rewards words based on commonality
42
- # Reward/penalize words based on line indexes and common letters
43
- #
44
- def select_words_with_scores
33
+ def select_best_words_with_scores
45
34
  selected_words = [@start_word]
46
35
  selected_word_scores = [@start_word.score]
47
36
  seen_black_chars = @start_word.black_chars
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class WordleDecoder
4
- VERSION = "0.1.2"
4
+ VERSION = "0.1.5"
5
5
  end
@@ -23,7 +23,7 @@ class WordleDecoder
23
23
  end
24
24
 
25
25
  def chars
26
- @chars ||= @word_str.split("")
26
+ @chars ||= @word_str.chars
27
27
  end
28
28
 
29
29
  COMMON_LETTERS = %w[s e a o r i l t n].freeze
@@ -5,7 +5,9 @@ class WordleDecoder
5
5
  EMOJI_HINT_CHARS = { "⬛" => "b",
6
6
  "⬜" => "b",
7
7
  "🟨" => "y",
8
- "🟩" => "g" }.freeze
8
+ "🟦" => "y",
9
+ "🟩" => "g",
10
+ "🟧" => "g" }.freeze
9
11
 
10
12
  def initialize(hint_line, line_index, answer_chars)
11
13
  @hint_chars = normalize_hint_chars(hint_line)
@@ -143,7 +145,21 @@ class WordleDecoder
143
145
  end
144
146
 
145
147
  def impossible_words(commonality)
146
- WordSearch.chars_at_index(@answer_chars, @index, commonality)
148
+ words = WordSearch.chars_at_index(@answer_chars, @index, commonality)
149
+ reject_possible_words_where_letter_appears_multiple_times_and_is_in_answer!(words)
150
+ words
151
+ end
152
+
153
+ private
154
+
155
+ def reject_possible_words_where_letter_appears_multiple_times_and_is_in_answer!(words)
156
+ words.reject! do |word|
157
+ chars = word.chars
158
+ index_char = chars[@index]
159
+ chars.each_with_index.any? do |char, idx|
160
+ char == index_char && idx != @index && @answer_chars.include?(char)
161
+ end
162
+ end
147
163
  end
148
164
  end
149
165
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'json'
3
+ require "json"
4
4
 
5
5
  class WordleDecoder
6
6
  class WordSearch
@@ -2,10 +2,28 @@
2
2
 
3
3
  class WordleDecoder
4
4
  class WordleShare
5
- ANSWER_LINES = ["🟩🟩🟩🟩🟩", "ggggg"].freeze
5
+ ANSWER_LINES = ["🟩🟩🟩🟩🟩",
6
+ "🟧🟧🟧🟧🟧"].freeze
6
7
 
7
- def self.final_line?(input_lines)
8
- ANSWER_LINES.any? { input_lines.include?(_1) }
8
+ def self.final_line?(input_line)
9
+ line = normalize_wordle_line(input_line.strip)
10
+ ANSWER_LINES.include?(line)
11
+ end
12
+
13
+ def self.normalize_wordle_line(line)
14
+ line = translate_emoji_shortcodes(line)
15
+ line.each_grapheme_cluster.map { |cluster| cluster.codepoints.first }.pack("U*")
16
+ end
17
+
18
+ SHORTCODES_TO_EMOJIS = { ":black_large_square:" => "⬛",
19
+ ":white_large_square:" => "⬜",
20
+ ":large_green_square:" => "🟩",
21
+ ":large_yellow_square:" => "🟨",
22
+ ":large_orange_square:" => "🟧",
23
+ ":large_blue_square:" => "🟦" }.freeze
24
+
25
+ def self.translate_emoji_shortcodes(line)
26
+ SHORTCODES_TO_EMOJIS.reduce(line) { |acc, (key, val)| acc.gsub(key, val) }
9
27
  end
10
28
 
11
29
  NEEDS_HELP_INPUTS = %w[help what wordle wat ? man okay yes no test].freeze
@@ -60,7 +78,7 @@ class WordleDecoder
60
78
  end
61
79
 
62
80
  def answer_chars
63
- @answer_chars ||= answer&.strip&.split("")
81
+ @answer_chars ||= answer&.strip&.chars
64
82
  end
65
83
 
66
84
  def hint_lines
@@ -99,8 +117,9 @@ class WordleDecoder
99
117
  VALID_HINT_CHARS = WordPosition::EMOJI_HINT_CHARS.to_a.flatten.uniq
100
118
 
101
119
  def parse_wordle_lines!
102
- input_lines.select do |line|
103
- line.each_char.all? { |c| VALID_HINT_CHARS.include?(c) }
120
+ input_lines.filter_map do |line|
121
+ line = self.class.normalize_wordle_line(line)
122
+ line if line.each_char.all? { |c| VALID_HINT_CHARS.include?(c) }
104
123
  end
105
124
  end
106
125
 
@@ -36,7 +36,7 @@ class WordleDecoder
36
36
 
37
37
  def to_terminal
38
38
  str = +"\n"
39
- best_guess.words_with_scores.reverse_each do |word, guess_score|
39
+ best_guess.best_words_with_scores.reverse_each do |word, guess_score|
40
40
  str << " #{word.to_terminal} #{word.confidence_score(guess_score)}\n"
41
41
  end
42
42
  str << " {{green:#{@wordle_share.answer}}}\n"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wordle_decoder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Ruzicka
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-05 00:00:00.000000000 Z
11
+ date: 2022-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cli-ui
@@ -24,7 +24,7 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.5'
27
- description: Given your Wordle share text, with some degree of confidence, the decoder
27
+ description: Given your Wordle share text, with some degree of confidence,the decoder
28
28
  will spit back the five-letter words it thinks you played.
29
29
  email:
30
30
  executables:
@@ -59,6 +59,7 @@ licenses:
59
59
  metadata:
60
60
  homepage_uri: https://github.com/mattruzicka/wordle_decoder
61
61
  source_code_uri: https://github.com/mattruzicka/wordle_decoder
62
+ rubygems_mfa_required: 'true'
62
63
  post_install_message:
63
64
  rdoc_options: []
64
65
  require_paths: