biscotti 0.1.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 +7 -0
- data/.gitignore +53 -0
- data/.rspec +3 -0
- data/.rubocop.yml +42 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/COPYING +675 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +102 -0
- data/Guardfile +46 -0
- data/README.md +56 -0
- data/Rakefile +8 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/biscotti.gemspec +31 -0
- data/data/biscotti/words.lst +234369 -0
- data/exe/biscotti +52 -0
- data/lib/biscotti.rb +46 -0
- data/lib/biscotti/cli.rb +13 -0
- data/lib/biscotti/version.rb +5 -0
- metadata +107 -0
data/exe/biscotti
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
Signal.trap('INT') { exit(130) }
|
5
|
+
Signal.trap('SIGINT') { exit(130) }
|
6
|
+
Signal.trap('TERM') { exit(143) }
|
7
|
+
|
8
|
+
require 'bundler/setup'
|
9
|
+
|
10
|
+
require 'biscotti'
|
11
|
+
require 'biscotti/cli'
|
12
|
+
|
13
|
+
require 'optparse'
|
14
|
+
|
15
|
+
OptionParser.new do |opts|
|
16
|
+
opts.banner = 'Usage: bundle exec biscotti [--version] [--help] <letters>'
|
17
|
+
|
18
|
+
opts.on('-V', '--version', 'Print version info') do
|
19
|
+
$stdout.puts("biscotti version #{Biscotti::VERSION}")
|
20
|
+
exit(0)
|
21
|
+
end
|
22
|
+
|
23
|
+
# TODO: Print dictionary
|
24
|
+
# TODO: Minimum character count
|
25
|
+
# TODO: Provide a custom dictionary
|
26
|
+
# TODO: Output as a grouped list by word length
|
27
|
+
|
28
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
29
|
+
warn(opts)
|
30
|
+
exit(0)
|
31
|
+
end
|
32
|
+
end.parse!
|
33
|
+
|
34
|
+
# raise 'File not processable' unless Biscotti::CLI.processable?
|
35
|
+
|
36
|
+
begin
|
37
|
+
dictionary = Biscotti.load_dictionary(File.join(Dir.pwd, 'data', 'biscotti', 'words.lst').freeze)
|
38
|
+
letters = ARGV.flat_map { |word| word.downcase.split('') }.sort.join
|
39
|
+
min_word_length = 2
|
40
|
+
|
41
|
+
output = Biscotti.find_words(
|
42
|
+
letters,
|
43
|
+
dictionary: dictionary,
|
44
|
+
min_word_length: min_word_length
|
45
|
+
)
|
46
|
+
|
47
|
+
output.each do |word|
|
48
|
+
$stdout.puts(word)
|
49
|
+
end
|
50
|
+
rescue Errno::EPIPE
|
51
|
+
exit(74)
|
52
|
+
end
|
data/lib/biscotti.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'biscotti/version'
|
4
|
+
|
5
|
+
module Biscotti
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def letters_frequency_idx(letters)
|
9
|
+
Hash[
|
10
|
+
letters
|
11
|
+
.group_by { |x| letters.count { |y| x == y } }
|
12
|
+
.flat_map do |k, v|
|
13
|
+
v.uniq.map { |l| [l, k] }
|
14
|
+
end
|
15
|
+
]
|
16
|
+
end
|
17
|
+
|
18
|
+
def load_dictionary(dictionary_file)
|
19
|
+
File.open(dictionary_file, 'r').readlines
|
20
|
+
end
|
21
|
+
|
22
|
+
def word_length_idx(words)
|
23
|
+
words.group_by(&:length)
|
24
|
+
end
|
25
|
+
|
26
|
+
def find_words(input, min_word_length: 2, dictionary: [])
|
27
|
+
puts "#{dictionary.count} words in dictionary"
|
28
|
+
|
29
|
+
letters = input.split('').sort
|
30
|
+
|
31
|
+
letters_frequency_idx = Biscotti.letters_frequency_idx(letters)
|
32
|
+
|
33
|
+
words = letters.count.downto(min_word_length).each_with_object([]) do |letter_count, w|
|
34
|
+
w.concat(letters.permutation(letter_count).to_a.map(&:join))
|
35
|
+
end
|
36
|
+
|
37
|
+
words & dictionary
|
38
|
+
.map(&:chomp)
|
39
|
+
.select { |word| word.length >= min_word_length }
|
40
|
+
.select { |word| word.length <= letters.count }
|
41
|
+
.map { |word| word.strip.downcase.split('') }
|
42
|
+
.select { |word| (word - letters).empty? }
|
43
|
+
.select { |word| word.all? { |l0| word.count { |l1| l1 == l0 } <= letters_frequency_idx[l0] } }
|
44
|
+
.map(&:join)
|
45
|
+
end
|
46
|
+
end
|
data/lib/biscotti/cli.rb
ADDED
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: biscotti
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mike Hall
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-08-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
description: Generate a list of possible words for a given set of letters.
|
56
|
+
email:
|
57
|
+
- mike@just3ws.com
|
58
|
+
executables:
|
59
|
+
- biscotti
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".gitignore"
|
64
|
+
- ".rspec"
|
65
|
+
- ".rubocop.yml"
|
66
|
+
- ".ruby-gemset"
|
67
|
+
- ".ruby-version"
|
68
|
+
- ".travis.yml"
|
69
|
+
- COPYING
|
70
|
+
- Gemfile
|
71
|
+
- Gemfile.lock
|
72
|
+
- Guardfile
|
73
|
+
- README.md
|
74
|
+
- Rakefile
|
75
|
+
- bin/console
|
76
|
+
- bin/setup
|
77
|
+
- biscotti.gemspec
|
78
|
+
- data/biscotti/words.lst
|
79
|
+
- exe/biscotti
|
80
|
+
- lib/biscotti.rb
|
81
|
+
- lib/biscotti/cli.rb
|
82
|
+
- lib/biscotti/version.rb
|
83
|
+
homepage: https://github.com/just3ws/biscotti
|
84
|
+
licenses:
|
85
|
+
- GPL-3.0+
|
86
|
+
metadata: {}
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
requirements: []
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 2.7.7
|
104
|
+
signing_key:
|
105
|
+
specification_version: 4
|
106
|
+
summary: Totally not a way to cheat at letter scramble games.
|
107
|
+
test_files: []
|