wordle 0.3.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.tool-versions +1 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile.lock +10 -1
- data/README.md +14 -1
- data/lib/integer.rb +13 -0
- data/lib/wordle/game.rb +31 -15
- data/lib/wordle/guess_analyzer.rb +64 -14
- data/lib/wordle/guess_validator.rb +46 -7
- data/lib/wordle/legend.rb +2 -0
- data/lib/wordle/list.rb +10 -4
- data/lib/wordle/options.rb +29 -0
- data/lib/wordle/version.rb +1 -1
- data/lib/wordle.rb +4 -0
- data/wordle.gemspec +1 -0
- metadata +21 -5
- data/sig/wordle.rbs +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4aa10bd48df4f525022634f4a41a1c4009f25e6da6bd9992470c2c963f08a91c
|
4
|
+
data.tar.gz: 99047acbf6078ca14d65aaaf71d0727fbb489557d58c72ed02c41d67bbb9b22e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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="
|
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
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
|
24
|
+
while guesses.length < 6 && !winner
|
25
25
|
guess = gets.chomp
|
26
26
|
|
27
|
-
validator = GuessValidator.new(
|
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 "
|
55
|
+
puts "\nWordle Gem #{hash} #{guesses.length}/6\n\n"
|
46
56
|
else
|
47
|
-
puts "
|
48
|
-
puts "
|
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
|
-
@
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
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
|
-
|
6
|
-
|
7
|
-
|
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
|
18
|
-
|
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
|
-
|
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
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
|
data/lib/wordle/version.rb
CHANGED
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
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.
|
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-
|
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.
|
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