wordle_decoder 0.1.4 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -1
- data/Gemfile.lock +1 -1
- data/LICENSE.md +11 -1
- data/README.md +4 -0
- data/bin/wordle_decoder +3 -0
- data/lib/wordle_decoder/guess.rb +6 -17
- data/lib/wordle_decoder/version.rb +1 -1
- data/lib/wordle_decoder/word_position.rb +18 -2
- data/lib/wordle_decoder/word_search.rb +2 -2
- data/lib/wordle_decoder/wordle_share.rb +21 -19
- data/lib/wordle_decoder.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 142d0e03da9022f5d873efb10f7afdb33da950bdbe1d13140e71dc30bb6dd31e
|
4
|
+
data.tar.gz: 7621746e54d4f3be4ba98b8e933d9d427386c6cbf0167a19408a8b89c7c5e4b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c3927f1af5e0b16acf3a40337a3a5a12b2da1d959cabec515b56cb955a2ad42311958a6e39e132834ee545393524e47e04ad5c6169ccf4df5d858da9f249910
|
7
|
+
data.tar.gz: 8e02f0dfd8b94f99d655ea2aa647b2a96aa80b6dc5545eacda109a92ac6f66157043b4f20eaef9e39a985e9eb36f37c2ec05aacb01d80c8d373c9ea3aa279eca
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,22 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.1.7] - 2022-04-02
|
4
|
+
|
5
|
+
- Don't fail when the answer contains an "x" - https://github.com/mattruzicka/wordle_decoder/issues/5
|
6
|
+
|
7
|
+
## [0.1.6] - 2022-03-20
|
8
|
+
|
9
|
+
- Updated license - [58dd8f5](https://github.com/mattruzicka/wordle_decoder/commit/58dd8f50eb1d115236c2b14a25b39e598e6955ec)
|
10
|
+
|
11
|
+
## [0.1.5] - 2022-03-20
|
12
|
+
|
13
|
+
- Support high contrast mode - https://github.com/mattruzicka/wordle_decoder/issues/4
|
14
|
+
- 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
|
15
|
+
- Found some old notes/TODOs I took while on a walk and forgot about - [4201916](https://github.com/mattruzicka/wordle_decoder/commit/4201916b47f84ba7ee851db938b8dba36eb64236)
|
16
|
+
|
3
17
|
## [0.1.4] - 2022-03-06
|
4
18
|
|
5
|
-
-
|
19
|
+
- Deal with weird input chars - https://github.com/mattruzicka/wordle_decoder/issues/2
|
6
20
|
|
7
21
|
## [0.1.3] - 2022-03-05
|
8
22
|
|
data/Gemfile.lock
CHANGED
data/LICENSE.md
CHANGED
@@ -1 +1,11 @@
|
|
1
|
-
|
1
|
+
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. To view a copy of this license, visit [http://creativecommons.org/licenses/by-nc-sa/4.0/](http://creativecommons.org/licenses/by-nc-sa/4.0/) or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
|
2
|
+
|
3
|
+
I spent a decent amount of time on this thing and I'd hate to see someone slap some ads on top of it without at least contacting (and paying) me. If you do have a way to make money off this weird little project, awesome! I want some!
|
4
|
+
|
5
|
+
Also, I've only ever used the standard MIT license, so I thought it'd be interesting to try something different.
|
6
|
+
|
7
|
+
Feel free to open an issue or contact me directly with questions.
|
8
|
+
|
9
|
+
Thanks,
|
10
|
+
|
11
|
+
[@mattruzicka](https://twitter.com/mattruzicka)
|
data/README.md
CHANGED
@@ -27,6 +27,10 @@ Wordle 258 3/6
|
|
27
27
|
```
|
28
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
29
|
|
30
|
+
## Example
|
31
|
+
|
32
|
+
<img width="528" alt="Screen Shot 2022-03-19 at 4 45 59 PM" src="https://user-images.githubusercontent.com/806788/159139538-fc58bc6f-8cfe-44d1-9177-5072e42ea318.png">
|
33
|
+
|
30
34
|
## Why?
|
31
35
|
|
32
36
|
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.
|
data/bin/wordle_decoder
CHANGED
@@ -134,6 +134,9 @@ 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
|
data/lib/wordle_decoder/guess.rb
CHANGED
@@ -9,19 +9,19 @@ class WordleDecoder
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def score
|
12
|
-
@score ||=
|
12
|
+
@score ||= best_words_with_scores.sum(&:last)
|
13
13
|
end
|
14
14
|
|
15
15
|
def word_scores
|
16
|
-
@word_scores ||=
|
16
|
+
@word_scores ||= best_words_with_scores.map(&:last)
|
17
17
|
end
|
18
18
|
|
19
19
|
def words
|
20
|
-
@words ||=
|
20
|
+
@words ||= best_words_with_scores.map { |w, _s| w.to_s }
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
@
|
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
|
@@ -5,7 +5,9 @@ class WordleDecoder
|
|
5
5
|
EMOJI_HINT_CHARS = { "⬛" => "b",
|
6
6
|
"⬜" => "b",
|
7
7
|
"🟨" => "y",
|
8
|
-
"
|
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
|
@@ -15,11 +15,11 @@ class WordleDecoder
|
|
15
15
|
less_common_letter_to_words_arrays[index][char]
|
16
16
|
when :least
|
17
17
|
least_common_letter_to_words_arrays[index][char]
|
18
|
-
end
|
18
|
+
end || []
|
19
19
|
end
|
20
20
|
|
21
21
|
def chars_at_index(chars, index, commonality)
|
22
|
-
chars.uniq.flat_map { |
|
22
|
+
chars.uniq.flat_map { |char| char_at_index(char, index, commonality) }
|
23
23
|
end
|
24
24
|
|
25
25
|
def frequency_score(word)
|
@@ -3,11 +3,27 @@
|
|
3
3
|
class WordleDecoder
|
4
4
|
class WordleShare
|
5
5
|
ANSWER_LINES = ["🟩🟩🟩🟩🟩",
|
6
|
-
"
|
7
|
-
":large_green_square:" * 5].freeze
|
6
|
+
"🟧🟧🟧🟧🟧"].freeze
|
8
7
|
|
9
|
-
def self.final_line?(
|
10
|
-
|
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) }
|
11
27
|
end
|
12
28
|
|
13
29
|
NEEDS_HELP_INPUTS = %w[help what wordle wat ? man okay yes no test].freeze
|
@@ -102,25 +118,11 @@ class WordleDecoder
|
|
102
118
|
|
103
119
|
def parse_wordle_lines!
|
104
120
|
input_lines.filter_map do |line|
|
105
|
-
line = normalize_wordle_line(line)
|
121
|
+
line = self.class.normalize_wordle_line(line)
|
106
122
|
line if line.each_char.all? { |c| VALID_HINT_CHARS.include?(c) }
|
107
123
|
end
|
108
124
|
end
|
109
125
|
|
110
|
-
def normalize_wordle_line(line)
|
111
|
-
line = translate_emoji_shortcodes(line)
|
112
|
-
line.each_grapheme_cluster.map { |cluster| cluster.codepoints.first }.pack("U*")
|
113
|
-
end
|
114
|
-
|
115
|
-
SHORTCODES_TO_EMOJIS = { ":black_large_square:" => "⬛",
|
116
|
-
":white_large_square:" => "⬜",
|
117
|
-
":large_green_square:" => "🟩",
|
118
|
-
":large_yellow_square:" => "🟨" }.freeze
|
119
|
-
|
120
|
-
def translate_emoji_shortcodes(line)
|
121
|
-
SHORTCODES_TO_EMOJIS.reduce(line) { |acc, (key, val)| acc.gsub(key, val) }
|
122
|
-
end
|
123
|
-
|
124
126
|
def parse_input_lines!
|
125
127
|
case input
|
126
128
|
when String
|
data/lib/wordle_decoder.rb
CHANGED
@@ -36,7 +36,7 @@ class WordleDecoder
|
|
36
36
|
|
37
37
|
def to_terminal
|
38
38
|
str = +"\n"
|
39
|
-
best_guess.
|
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.
|
4
|
+
version: 0.1.7
|
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-
|
11
|
+
date: 2022-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cli-ui
|
@@ -55,7 +55,7 @@ files:
|
|
55
55
|
- sig/wordle_decoder.rbs
|
56
56
|
homepage: https://github.com/mattruzicka/wordle_decoder
|
57
57
|
licenses:
|
58
|
-
- CC-BY-NC-SA-
|
58
|
+
- CC-BY-NC-SA-4.0
|
59
59
|
metadata:
|
60
60
|
homepage_uri: https://github.com/mattruzicka/wordle_decoder
|
61
61
|
source_code_uri: https://github.com/mattruzicka/wordle_decoder
|