wordle_decoder 0.1.1 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 19def1e6b5fe6f2513d21327fd4862c0a4e3db8d01775463633f9bd2eec03dd0
4
- data.tar.gz: 9a6e2f43a258eb186359491e5090f811ab27792cc945a93eca0ab5b714080af8
3
+ metadata.gz: 1b287c675238c8e02b76dd2fcb7c6811837831e2245954a9465a2f1d6634ecb5
4
+ data.tar.gz: 1d0f11cdd67b6443ebc6362daf666e82006c361b23a9847ee8c1a3020eeea1ad
5
5
  SHA512:
6
- metadata.gz: 0de9cbfba9ec0edaca95e4259e21efc79566979e9874841e4c1bd7a9f4462e60a41db6bf4881f15baca5d466b66a0043f74dcad2b2f2b2815b0c07f43373fc49
7
- data.tar.gz: 378f8d47d3b8a1043c197e3feb1652fdb8398102b51bfb690788a70cad7a1a2f3cccdfe12fcbd5b8051e39c52ff3a6bad1c632e98bf0579309ae3c93dd5d2305
6
+ metadata.gz: 4dcdc6aa0b31fd576fc973bd35ff7681ae4e054009d62f81afa00a25088e06e81e4c128068de5c524d4e30668b49bd0847e2354f5f614e80fab0e48a7c56c75d
7
+ data.tar.gz: d414927380ff8e1832c7eb70b1e9f632dc41357d586f1f9674cda5f8161e0d6e2c3ff393677b45fab47155d2b56dac1f6edf4a446003da4b4b2fdbf2399af6aa
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,9 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.1.0] - 2022-02-22
3
+ ## [0.1.4] - 2022-03-06
4
4
 
5
- - Initial release
5
+ - Deal with weird input chars - https://github.com/mattruzicka/wordle_decoder/issues/2
6
+
7
+ ## [0.1.3] - 2022-03-05
8
+
9
+ - 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.3)
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
@@ -8,16 +8,28 @@ require "cli/ui"
8
8
 
9
9
  CLI::UI::StdoutRouter.enable
10
10
 
11
- print CLI::UI.fmt("\n\n Share your Wordle:\n\n {{blue:>}} ")
11
+ print CLI::UI.fmt("\n Share your wordle:\n\n{{blue:>}} ")
12
12
 
13
13
  input_lines = []
14
14
  until WordleDecoder::WordleShare.final_line?(input_line = gets)
15
15
  input_lines << input_line
16
+ if WordleDecoder::WordleShare.exit_program?(input_line)
17
+ puts "\n Goodbye!\n\n"
18
+ return
19
+ elsif WordleDecoder::WordleShare.needs_help?(input_line)
20
+ help_text = WordleDecoder::WordleShare.help_to_terminal
21
+ input_lines << "\n"
22
+ input_lines << help_text
23
+ input_lines << "\n"
24
+ print CLI::UI.fmt(help_text)
25
+ elsif input_lines.all? { |l| l.strip.empty? }
26
+ print CLI::UI.fmt("{{blue:>}} ")
27
+ end
16
28
  end
17
29
  input_lines << input_line
18
30
 
19
- clear_pasted_text_lines = input_lines.reverse_each.map { |line| "\033[A\r #{" " * line.length}" }
20
- clear_pasted_text_lines << "\033[A\r"
31
+ clear_pasted_text_lines = input_lines.reverse_each.map { |line| "\033[A\r #{" " * line.length}" }
32
+ clear_pasted_text_lines << "\033[A\r "
21
33
  puts clear_pasted_text_lines.join
22
34
 
23
35
  wordle_share = WordleDecoder::WordleShare.new(input_lines)
@@ -47,78 +59,84 @@ CLI::UI::Spinner.spin("Acting like I'm doing something.") do |spinner|
47
59
  end
48
60
  spinner.update_title("Fine, I'll do it")
49
61
 
50
- decoder.to_terminal
51
- spinner.update_title("\r I decoded your hints!}}")
62
+ if decoder.best_guess
63
+ spinner.update_title("\r I decoded your wordle hints!}}")
64
+ else
65
+ no_guess_messages = ["You stumped me!", "Are you messing with me?", "Are you sure that was the word of the day?"]
66
+ spinner.update_title("\r 🤨 #{no_guess_messages.sample}}}")
67
+ end
68
+ end
69
+
70
+ if decoder.best_guess
71
+ puts CLI::UI.fmt("\n {{blue:{{underline:Guesses}} {{underline:Confidence}}}}")
72
+ puts CLI::UI.fmt(decoder.to_terminal)
52
73
  end
53
74
 
54
- puts CLI::UI.fmt("\n\n {{blue:{{underline:Guesses}} {{underline:Confidence}}}}")
55
- puts CLI::UI.fmt(decoder.to_terminal)
56
-
57
- comments = ["Maybe some of those are your words!",
58
- "I tried!",
59
- "How'd I do?",
60
- "Did I get it?",
61
- "I'm also guessing you're great!",
62
- "Don't spill your coffee.",
63
- "Shout out to friends for sending me their wordles.",
64
- "Shout out to https://www.youtube.com/watch?v=v68zYyaEmEA for word frequency source.",
65
- "I hope you had a great time.",
66
- "Hope to see you again.",
67
- "Was great guessing you.",
68
- "Thinking about heading to sleep.",
69
- "Sometimes I just throw out mostly random stuff.",
70
- "I didn't mean to offend.",
71
- "I try not to be random...",
72
- "I'm open source :)",
73
- "I'd fork you to make me better.",
74
- "TLDR: Another programmer played wordle.",
75
- "How was I with my words?",
76
- "I'm written in Ruby and bite like a python.",
77
- "Here's an emoji ❤️",
78
- "🤔 🤨 🧐",
79
- "All my thinking to you.",
80
- "I've learned about wordle and your people.",
81
- "I'm not learning anything at the moment.",
82
- "I wish I had time to machine learn you ;)",
83
- "No, you have a great personality!",
84
- "This one might be weird, if it's your first.",
85
- "Is my strategy as good as yours?",
86
- "I'm biased, but so are you!",
87
- "I'd love to learn your strategy ;)",
88
- "I'd grow neurons for you.",
89
- "How well can you play without me guessing?",
90
- "If you're seeing this, we probably know each other.",
91
- "I hope things aren't getting too weird.",
92
- "❤️ ❤️ ❤️",
93
- "No, you're great!",
94
- "Do you decode often?",
95
- "All the best five-letter words to you!",
96
- "My friends call me the wordle decoder.",
97
- "Everything I am is written.",
98
- "May my written code speak truly.",
99
- "Who guessed better?",
100
- "No excuse, but my thoughts are in a constant array.",
101
- "Your words complete me.",
102
- "Like peering into a soul.",
103
- "I hope I didn't embarass myself.",
104
- "I hope I didn't embarrass myself.",
105
- "I hope I didn't embaras myself.",
106
- "Can you decode my five letter word?",
107
- "Sometimes I'm off by one...",
108
- "Something's fishy...",
109
- "Did you put something on me?",
110
- "I'm only wrong about five letter words...",
111
- "Your words are beautiful.",
112
- "You make this wordle a better place!",
113
- "What in the wordle was I thinking?",
114
- "Those words you gave me were so good.",
115
- "I truly enjoyed those words, thank you!",
116
- "What lovely words you have!",
117
- "I hope my words were as good as yours!",
118
- "Please enjoy the rest of your day!",
119
- "I may not be positive about your words, but I am about you!",
120
- "Thank you for spending time with me!",
121
- "I enjoyed our time together!"].freeze
122
-
123
- puts CLI::UI.fmt("\n #{comments.sample}\n " \
124
- "{{blue:https://github.com/mattruzicka/wordle_decoder}}}}\n\n")
75
+ salutations = ["Maybe some of those are your words!",
76
+ "I tried!",
77
+ "How'd I do?",
78
+ "Did I get it?",
79
+ "I'm also guessing you're great!",
80
+ "Don't spill your coffee.",
81
+ "Shout out to friends for sending me their wordles.",
82
+ "Shout out to https://www.youtube.com/watch?v=v68zYyaEmEA for word frequency source.",
83
+ "I hope you had a great time.",
84
+ "Hope to see you again.",
85
+ "Was great guessing you.",
86
+ "Thinking about heading to sleep.",
87
+ "Sometimes I just throw out mostly random stuff.",
88
+ "I didn't mean to offend.",
89
+ "I try not to be random...",
90
+ "I'm open source :)",
91
+ "I'd fork you to make me better.",
92
+ "TLDR: Another programmer played wordle.",
93
+ "How was I with my words?",
94
+ "I'm written in Ruby and bite like a python.",
95
+ "Here's an emoji ❤️",
96
+ "🤔 🤨 🧐",
97
+ "All my thinking to you.",
98
+ "I've learned about wordle and your people.",
99
+ "I'm not learning anything at the moment.",
100
+ "I wish I had time to machine learn you ;)",
101
+ "No, you have a great personality!",
102
+ "This one might be weird, if it's your first.",
103
+ "Is my strategy as good as yours?",
104
+ "I'm biased, but so are you!",
105
+ "I'd love to learn your strategy ;)",
106
+ "I'd grow neurons for you.",
107
+ "How well can you play without me guessing?",
108
+ "If you're seeing this, we probably know each other.",
109
+ "I hope things aren't getting too weird.",
110
+ "❤️ ❤️ ❤️",
111
+ "No, you're great!",
112
+ "Do you decode often?",
113
+ "All the best five-letter words to you!",
114
+ "My friends call me the wordle decoder.",
115
+ "Everything I am is written.",
116
+ "May my written code speak truly.",
117
+ "Who guessed better?",
118
+ "No excuse, but my thoughts are in a constant array.",
119
+ "Your words complete me.",
120
+ "Like peering into a soul.",
121
+ "I hope I didn't embarass myself.",
122
+ "I hope I didn't embarrass myself.",
123
+ "I hope I didn't embaras myself.",
124
+ "Can you decode my five letter word?",
125
+ "Sometimes I'm off by one...",
126
+ "Something's fishy...",
127
+ "Did you put something on me?",
128
+ "I'm only wrong about five letter words...",
129
+ "Your words are beautiful.",
130
+ "You make this wordle a better place!",
131
+ "What in the wordle was I thinking?",
132
+ "Those words you gave me were so good.",
133
+ "I truly enjoyed those words, thank you!",
134
+ "What lovely words you have!",
135
+ "I hope my words were as good as yours!",
136
+ "Please enjoy the rest of your day!",
137
+ "I may not be positive about your words, but I am about you!",
138
+ "Thank you for spending time with me!",
139
+ "I enjoyed our time together!"].freeze
140
+
141
+ puts CLI::UI.fmt("\n\n #{salutations.sample}\n " \
142
+ "{{blue:https://github.com/mattruzicka/wordle_decoder}}}}\n\n")
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class WordleDecoder
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.4"
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
@@ -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,12 +2,31 @@
2
2
 
3
3
  class WordleDecoder
4
4
  class WordleShare
5
- ANSWER_LINES = ["🟩🟩🟩🟩🟩", "ggggg"].freeze
5
+ ANSWER_LINES = ["🟩🟩🟩🟩🟩",
6
+ "ggggg",
7
+ ":large_green_square:" * 5].freeze
6
8
 
7
9
  def self.final_line?(input_lines)
8
10
  ANSWER_LINES.any? { input_lines.include?(_1) }
9
11
  end
10
12
 
13
+ NEEDS_HELP_INPUTS = %w[help what wordle wat ? man okay yes no test].freeze
14
+
15
+ def self.needs_help?(input)
16
+ NEEDS_HELP_INPUTS.include?(input.strip.downcase)
17
+ end
18
+
19
+ EXIT_PROGRAM_INPUTS = %w[exit no nvm].freeze
20
+
21
+ def self.exit_program?(input)
22
+ EXIT_PROGRAM_INPUTS.include?(input.strip)
23
+ end
24
+
25
+ def self.help_to_terminal
26
+ "\n {{italic:Copy and paste those 🟨, 🟩, and ⬛" \
27
+ " emojis from your wordle share.}} \n\n{{blue:>}} "
28
+ end
29
+
11
30
  def self.wordle_answers
12
31
  @wordle_answers ||= load_worldle_ansers
13
32
  end
@@ -36,12 +55,14 @@ class WordleDecoder
36
55
 
37
56
  def find_answer
38
57
  title_line = input_lines.detect { |line| line.match?(GAME_DAY_REGEX) }
58
+ return unless title_line
59
+
39
60
  game_day = title_line.match(GAME_DAY_REGEX).captures.first&.to_i
40
61
  self.answer = self.class.wordle_answers[game_day]
41
62
  end
42
63
 
43
64
  def answer_chars
44
- @answer_chars ||= answer&.strip&.split("")
65
+ @answer_chars ||= answer&.strip&.chars
45
66
  end
46
67
 
47
68
  def hint_lines
@@ -80,11 +101,26 @@ class WordleDecoder
80
101
  VALID_HINT_CHARS = WordPosition::EMOJI_HINT_CHARS.to_a.flatten.uniq
81
102
 
82
103
  def parse_wordle_lines!
83
- input_lines.select do |line|
84
- line.each_char.all? { |c| VALID_HINT_CHARS.include?(c) }
104
+ input_lines.filter_map do |line|
105
+ line = normalize_wordle_line(line)
106
+ line if line.each_char.all? { |c| VALID_HINT_CHARS.include?(c) }
85
107
  end
86
108
  end
87
109
 
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
+
88
124
  def parse_input_lines!
89
125
  case input
90
126
  when String
@@ -14,10 +14,6 @@ class WordleDecoder
14
14
  @wordle_share = wordle_share
15
15
  end
16
16
 
17
- def to_terminal
18
- @to_terminal ||= format_to_terminal
19
- end
20
-
21
17
  def best_guess
22
18
  @best_guess ||= guesses.first
23
19
  end
@@ -38,6 +34,14 @@ class WordleDecoder
38
34
  lines.join("\n")
39
35
  end
40
36
 
37
+ def to_terminal
38
+ str = +"\n"
39
+ best_guess.words_with_scores.reverse_each do |word, guess_score|
40
+ str << " #{word.to_terminal} #{word.confidence_score(guess_score)}\n"
41
+ end
42
+ str << " {{green:#{@wordle_share.answer}}}\n"
43
+ end
44
+
41
45
  private
42
46
 
43
47
  def initialize_and_sort_guesses
@@ -55,12 +59,4 @@ class WordleDecoder
55
59
  WordPosition.new(line, index, @wordle_share.answer_chars)
56
60
  end
57
61
  end
58
-
59
- def format_to_terminal
60
- str = +"\n"
61
- best_guess.words_with_scores.reverse_each do |word, guess_score|
62
- str << " #{word.to_terminal} #{word.confidence_score(guess_score)}\n"
63
- end
64
- str << " {{green:#{@wordle_share.answer}}}\n\n"
65
- end
66
62
  end
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.1
4
+ version: 0.1.4
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-06 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: