wordle 0.3.0 → 0.6.0

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: ff0c43c46f9e5e2e25088128a3cd8e2f634bda564b98a0b36473c0d9fb1a25b7
4
- data.tar.gz: bbcaf825639fd41c6388b501388cc108048d1c4464e59a3cad7eaa2451586679
3
+ metadata.gz: 4aa10bd48df4f525022634f4a41a1c4009f25e6da6bd9992470c2c963f08a91c
4
+ data.tar.gz: 99047acbf6078ca14d65aaaf71d0727fbb489557d58c72ed02c41d67bbb9b22e
5
5
  SHA512:
6
- metadata.gz: 366f914646b492bd8c00f4a4334db6ebb494b447cd54c34ea0d6c47310be1ab7ed3af5662c05daf5bcf8056dbb0899db2848599525ed17859eb40e6b111d500b
7
- data.tar.gz: 1a21fa7349041d534f29588cb45b9ca41e4e0deef0d6812de0e1384a80613a94667b925b3c32cacf9d6d99bc587807b0419f416a9b6ebe16cb43142d1de13cce
6
+ metadata.gz: a807bcfa10a95e25cb272da8d28a8bd65172e3d623ba76f8e0bc98fd8e4f8618e205a18b6ead77c79e3c21171b6801e64c729029cdbbd9615d713cef53767a87
7
+ data.tar.gz: 3e44a8f3ed4eb337de645d60d50399393206d56df15e29262d6a327ae52c3b2edf6dd8e9daee3eeaffb05d66470916cddf518113d2c4d0fb1a0eca720e976db0
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 3.1.0
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## [0.6.0] - 2022-04-14
2
+
3
+ - Adds hard mode.
4
+
5
+ ## [0.5.0] - 2022-02-02
6
+
7
+ - Prints outs squares for sharing at the end of a game.
8
+ - Sharing prints out unique hash for word that was played, which can be passed
9
+ to -i option so you can play the same word as a friend.
10
+
11
+ ## [0.4.0] - 2022-01-14
12
+
13
+ - Fixes bug where too many letters would get marked as yellow. Resolves
14
+ [https://github.com/JonathanWThom/wordle/issues/3](https://github.com/JonathanWThom/wordle/issues/3).
15
+
1
16
  ## [0.3.0] - 2022-01-10
2
17
 
3
18
  - Adds a better world list. From the Wordle source itself : )
data/Gemfile.lock CHANGED
@@ -1,19 +1,27 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- wordle (0.3.0)
4
+ wordle (0.6.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  ast (2.4.2)
10
+ debug (1.4.0)
11
+ irb (>= 1.3.6)
12
+ reline (>= 0.2.7)
10
13
  diff-lcs (1.5.0)
14
+ io-console (0.5.11)
15
+ irb (1.4.1)
16
+ reline (>= 0.3.0)
11
17
  parallel (1.21.0)
12
18
  parser (3.1.0.0)
13
19
  ast (~> 2.4.1)
14
20
  rainbow (3.0.0)
15
21
  rake (13.0.6)
16
22
  regexp_parser (2.2.0)
23
+ reline (0.3.1)
24
+ io-console (~> 0.5)
17
25
  rexml (3.2.5)
18
26
  rspec (3.10.0)
19
27
  rspec-core (~> 3.10.0)
@@ -53,6 +61,7 @@ PLATFORMS
53
61
  x86_64-linux
54
62
 
55
63
  DEPENDENCIES
64
+ debug (>= 1.0.0)
56
65
  rake (~> 13.0)
57
66
  rspec (~> 3.0)
58
67
  standard (~> 1.3)
data/README.md CHANGED
@@ -2,8 +2,9 @@
2
2
 
3
3
  Ruby implementation of [Wordle](https://www.powerlanguage.co.uk/wordle/).
4
4
 
5
- <img width="794" alt="Screen Shot 2022-01-10 at 9 18 19 PM" src="https://user-images.githubusercontent.com/22665228/148885575-39805830-274e-40e6-be14-4c6bc6db37ec.png">
5
+ <img width="869" alt="Screen Shot 2022-02-02 at 10 32 02 PM" src="https://user-images.githubusercontent.com/22665228/152292863-33743039-d9f4-4afa-a321-684d7b67cdb3.png">
6
6
 
7
+ [![Build](https://github.com/JonathanWThom/wordle/actions/workflows/build.yml/badge.svg)](https://github.com/JonathanWThom/wordle/actions/workflows/build.yml)
7
8
 
8
9
  ## Installation
9
10
 
@@ -13,6 +14,14 @@ Ruby implementation of [Wordle](https://www.powerlanguage.co.uk/wordle/).
13
14
 
14
15
  Just run `wordle` from the command line.
15
16
 
17
+ This version will pull a new word at random every time you run it from a very weird and long list. It's much more difficult than the original due to some of the words being a bit uncommon.
18
+
19
+ ```
20
+ Usage: wordle [options]
21
+ -i, --identifier=IDENTIFIER Pass word identifer to target a specific word that someone else has played. Identifier gets printed at the end of the game to share with a friend.
22
+ -d, --difficult Hard mode. Any revealed hints must be used in subsequent guesses.
23
+ ```
24
+
16
25
  ## Development
17
26
 
18
27
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -23,6 +32,10 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
23
32
 
24
33
  Bug reports and pull requests are welcome on GitHub at https://github.com/JonathanWThom/wordle. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/JonathanWThom/wordle/blob/main/CODE_OF_CONDUCT.md).
25
34
 
35
+ ## Acknowledgements
36
+
37
+ I cribbed my word list from the Wordle site itself. I have no association with the site, its creator, or the New York Times - I'm just a fan!
38
+
26
39
  ## License
27
40
 
28
41
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/lib/integer.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Integer
4
+ def ordinalize
5
+ {
6
+ 1 => "1st",
7
+ 2 => "2nd",
8
+ 3 => "3rd",
9
+ 4 => "4th",
10
+ 5 => "5th"
11
+ }[self]
12
+ end
13
+ end
data/lib/wordle/game.rb CHANGED
@@ -2,29 +2,35 @@
2
2
 
3
3
  module Wordle
4
4
  class Game
5
- def self.play
6
- new.play
5
+ def self.play(*args)
6
+ new(*args).play
7
7
  end
8
8
 
9
- def initialize
9
+ def initialize(options_reader = Options.new)
10
10
  @list = List.new
11
+ @options = options_reader.read
11
12
  @target_word = generate_word
12
13
  end
13
14
 
14
- # print letters that have already been used?
15
- # compare to real words
16
-
17
15
  def play
18
16
  winner = false
19
- attempts = 0
20
17
 
21
18
  Legend.print
22
19
  puts "Guess a 5 letter word: "
20
+ guesses = []
21
+ must_include = []
22
+ must_match = Array.new(5)
23
23
 
24
- while attempts < 6 && !winner
24
+ while guesses.length < 6 && !winner
25
25
  guess = gets.chomp
26
26
 
27
- validator = GuessValidator.new(guess, @list)
27
+ validator = GuessValidator.new(
28
+ guess,
29
+ @list,
30
+ @options[:difficult],
31
+ must_include,
32
+ must_match
33
+ )
28
34
  if validator.invalid?
29
35
  puts validator.error
30
36
  next
@@ -32,27 +38,37 @@ module Wordle
32
38
 
33
39
  analyzer = GuessAnalyzer.new(@target_word, guess)
34
40
  puts analyzer.colors
41
+ guesses << analyzer.squares
42
+ if @options[:difficult]
43
+ must_include = analyzer.must_include(must_include)
44
+ must_match = analyzer.must_match(must_match)
45
+ end
35
46
 
36
47
  if analyzer.match?
37
48
  winner = true
38
49
  break
39
50
  end
40
-
41
- attempts += 1
42
51
  end
43
52
 
53
+ hash = Digest::SHA2.hexdigest(@target_word)[..5]
44
54
  if winner
45
- puts "Winner!"
55
+ puts "\nWordle Gem #{hash} #{guesses.length}/6\n\n"
46
56
  else
47
- puts "Word was: #{@target_word}"
48
- puts "Better luck next time!"
57
+ puts "\nWord was: #{@target_word}\n"
58
+ puts "\nWordle Gem #{hash} X/6*\n\n"
49
59
  end
60
+
61
+ puts guesses
50
62
  end
51
63
 
52
64
  private
53
65
 
54
66
  def generate_word
55
- @list.random
67
+ if @options[:identifier]
68
+ @list.by_hash(@options[:identifier])
69
+ else
70
+ @list.random
71
+ end
56
72
  end
57
73
  end
58
74
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../string"
4
-
5
3
  module Wordle
6
4
  class GuessAnalyzer
7
5
  def initialize(target_word, guess)
@@ -14,21 +12,73 @@ module Wordle
14
12
  end
15
13
 
16
14
  def colors
17
- target_letters = @target_word.chars
18
- guess_letters = @guess.chars
19
- colored_letters = ""
20
-
21
- guess_letters.each_with_index do |letter, i|
22
- colored_letters += if letter == target_letters[i]
23
- letter.green
24
- elsif target_letters.include?(letter)
25
- letter.yellow
26
- else
27
- letter.gray
15
+ raw_colors.each_with_index.map do |color, i|
16
+ guess_letters[i].send(color)
17
+ end.join("")
18
+ end
19
+
20
+ def squares
21
+ color_map = {
22
+ green: "🟩",
23
+ yellow: "🟨",
24
+ gray: "⬛️"
25
+ }
26
+
27
+ raw_colors.each_with_index.map do |color, i|
28
+ color_map[color]
29
+ end.join("")
30
+ end
31
+
32
+ def must_include(prev_must_include)
33
+ raw_colors.each_with_index do |color, i|
34
+ if color == :yellow && !prev_must_include.include?(guess_letters[i])
35
+ prev_must_include << guess_letters[i]
36
+ end
37
+ end
38
+
39
+ prev_must_include
40
+ end
41
+
42
+ def must_match(prev_must_match)
43
+ raw_colors.each_with_index do |color, i|
44
+ if color == :green
45
+ prev_must_match[i] = guess_letters[i]
28
46
  end
29
47
  end
30
48
 
31
- colored_letters
49
+ prev_must_match
50
+ end
51
+
52
+ private
53
+
54
+ def guess_letters
55
+ @_guess_letters ||= @guess.chars
56
+ end
57
+
58
+ def raw_colors
59
+ @_raw_colors ||= begin
60
+ target_letters = @target_word.chars
61
+ colors = []
62
+
63
+ guess_letters.each_with_index do |letter, i|
64
+ if letter == target_letters[i]
65
+ colors[i] = :green
66
+ target_letters[i] = nil
67
+ end
68
+ end
69
+
70
+ guess_letters.each_with_index do |letter, i|
71
+ if colors[i].nil?
72
+ colors[i] = if target_letters.include?(letter)
73
+ :yellow
74
+ else
75
+ :gray
76
+ end
77
+ end
78
+ end
79
+
80
+ colors
81
+ end
32
82
  end
33
83
  end
34
84
  end
@@ -2,23 +2,62 @@
2
2
 
3
3
  module Wordle
4
4
  class GuessValidator
5
- attr_reader :error
6
-
7
- def initialize(guess, list)
5
+ def initialize(
6
+ guess,
7
+ list,
8
+ difficult,
9
+ must_include,
10
+ must_match
11
+ )
8
12
  @guess = guess
9
13
  @list = list
14
+ @difficult = difficult
15
+ @must_include = must_include
16
+ @must_match = must_match
17
+ @validated = false
10
18
  end
11
19
 
12
20
  def invalid?
21
+ !error.nil?
22
+ end
23
+
24
+ def error
25
+ validate if !@validated
26
+
27
+ @error
28
+ end
29
+
30
+ private
31
+
32
+ def validate
33
+ validate_normal_mode
34
+ validate_hard_mode if @difficult
35
+ @validated = true
36
+ end
37
+
38
+ def validate_normal_mode
13
39
  if @guess.length != 5
14
40
  @error = "Guess must be 5 letters long"
15
- return true
16
41
  elsif @list.invalid?(@guess)
17
- @error = "Guess must be a real word"
18
- return true
42
+ @error = "Guess not in word list"
43
+ end
44
+ end
45
+
46
+ def validate_hard_mode
47
+ @must_include.each do |letter|
48
+ if !@guess.include?(letter)
49
+ @error = "Guess must include #{letter}"
50
+ break
51
+ end
19
52
  end
20
53
 
21
- false
54
+ @guess.each_char.with_index do |letter, i|
55
+ match = @must_match[i]
56
+ if match && match != letter
57
+ @error = "#{(i + 1).ordinalize} letter must be #{match}"
58
+ break
59
+ end
60
+ end
22
61
  end
23
62
  end
24
63
  end
data/lib/wordle/legend.rb CHANGED
@@ -10,6 +10,8 @@ module Wordle
10
10
  puts green_example
11
11
  puts yellow_example
12
12
  puts gray_example
13
+ puts "\nRestart and add -i flag to target a specific word by hash, for example:"
14
+ puts "$ wordle -i ed541a\n\n"
13
15
  end
14
16
 
15
17
  private
data/lib/wordle/list.rb CHANGED
@@ -2,14 +2,20 @@
2
2
 
3
3
  module Wordle
4
4
  class List
5
- def initialize(length = 5)
6
- @length = length
7
- end
8
-
9
5
  def random
10
6
  list.sample.downcase.strip
11
7
  end
12
8
 
9
+ def by_hash(hash)
10
+ word = list.detect do |word|
11
+ Digest::SHA2.hexdigest(word.downcase.strip)[..5] == hash
12
+ end
13
+
14
+ raise Wordle::Error, "Invalid word identifier, are you sure you copied it correctly?" if word.nil?
15
+
16
+ word
17
+ end
18
+
13
19
  def invalid?(word)
14
20
  !list.include?(word)
15
21
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Wordle
4
+ class Options
5
+ def read
6
+ options = {}
7
+
8
+ parser = OptionParser.new do |opts|
9
+ opts.banner = "Usage: wordle [options]"
10
+
11
+ opts.on("-iIDENTIFIER", "--identifier=IDENTIFIER", "Pass word identifer to target a specific word that someone else has played. Identifier gets printed at the end of the game to share with a friend.") do |i|
12
+ options[:identifier] = i
13
+ end
14
+
15
+ opts.on("-d", "--difficult", "Hard mode. Any revealed hints must be used in subsequent guesses.") do |d|
16
+ options[:difficult] = d
17
+ end
18
+ end
19
+
20
+ begin
21
+ parser.parse!
22
+ rescue OptionParser::InvalidOption
23
+ puts "Option not recognized"
24
+ end
25
+
26
+ options
27
+ end
28
+ end
29
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Wordle
4
- VERSION = "0.3.0"
4
+ VERSION = "0.6.0"
5
5
  end
data/lib/wordle.rb CHANGED
@@ -1,7 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "digest"
4
+ require "optparse"
5
+ require_relative "integer"
3
6
  require_relative "string"
4
7
  require_relative "wordle/version"
8
+ require_relative "wordle/options"
5
9
  require_relative "wordle/source"
6
10
  require_relative "wordle/list"
7
11
  require_relative "wordle/guess_validator"
data/wordle.gemspec CHANGED
@@ -35,4 +35,5 @@ Gem::Specification.new do |spec|
35
35
 
36
36
  # For more information and examples about making a new gem, check out our
37
37
  # guide at: https://bundler.io/guides/creating_gem.html
38
+ spec.add_development_dependency "debug", ">= 1.0.0"
38
39
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wordle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Thom
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-11 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2022-04-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: debug
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.0.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.0.0
13
27
  description:
14
28
  email:
15
29
  - jonathanthom@hey.com
@@ -20,6 +34,7 @@ extra_rdoc_files: []
20
34
  files:
21
35
  - ".rspec"
22
36
  - ".standard.yml"
37
+ - ".tool-versions"
23
38
  - CHANGELOG.md
24
39
  - CODE_OF_CONDUCT.md
25
40
  - Gemfile
@@ -30,6 +45,7 @@ files:
30
45
  - bin/console
31
46
  - bin/setup
32
47
  - exe/wordle
48
+ - lib/integer.rb
33
49
  - lib/string.rb
34
50
  - lib/wordle.rb
35
51
  - lib/wordle/game.rb
@@ -37,9 +53,9 @@ files:
37
53
  - lib/wordle/guess_validator.rb
38
54
  - lib/wordle/legend.rb
39
55
  - lib/wordle/list.rb
56
+ - lib/wordle/options.rb
40
57
  - lib/wordle/source.rb
41
58
  - lib/wordle/version.rb
42
- - sig/wordle.rbs
43
59
  - wordle.gemspec
44
60
  homepage: https://github.com/jonathanwthom/wordle
45
61
  licenses:
@@ -64,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
80
  - !ruby/object:Gem::Version
65
81
  version: '0'
66
82
  requirements: []
67
- rubygems_version: 3.2.32
83
+ rubygems_version: 3.3.3
68
84
  signing_key:
69
85
  specification_version: 4
70
86
  summary: Wordle CLI in Ruby
data/sig/wordle.rbs DELETED
@@ -1,4 +0,0 @@
1
- module Wordle
2
- VERSION: String
3
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
- end