word_search 0.5.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.rubocop.yml +8 -5
- data/.ruby-version +1 -1
- data/.travis.yml +3 -2
- data/Gemfile +2 -1
- data/README.md +26 -4
- data/Rakefile +26 -12
- data/bin/console +5 -4
- data/bin/test +19 -0
- data/docs/Gemfile +8 -7
- data/docs/Gemfile.lock +31 -31
- data/docs/Rakefile +2 -1
- data/docs/config.rb +4 -3
- data/docs/source/images/logo.png +0 -0
- data/docs/source/images/search.png +0 -0
- data/docs/source/index.html.haml +49 -7
- data/docs/source/layouts/layout.html.haml +7 -9
- data/docs/source/stylesheets/site.css.sass +83 -0
- data/docs/vendor/cache/activesupport-5.0.1.gem +0 -0
- data/docs/vendor/cache/addressable-2.5.0.gem +0 -0
- data/docs/vendor/cache/backports-3.6.8.gem +0 -0
- data/docs/vendor/cache/coffee-script-2.4.1.gem +0 -0
- data/docs/vendor/cache/coffee-script-source-1.12.2.gem +0 -0
- data/docs/vendor/cache/compass-import-once-1.0.5.gem +0 -0
- data/docs/vendor/cache/concurrent-ruby-1.0.4.gem +0 -0
- data/docs/vendor/cache/contracts-0.13.0.gem +0 -0
- data/docs/vendor/cache/dotenv-2.1.1.gem +0 -0
- data/docs/vendor/cache/em-websocket-0.5.1.gem +0 -0
- data/docs/vendor/cache/erubis-2.7.0.gem +0 -0
- data/docs/vendor/cache/eventmachine-1.2.1.gem +0 -0
- data/docs/vendor/cache/execjs-2.7.0.gem +0 -0
- data/docs/vendor/cache/fast_blank-1.0.0.gem +0 -0
- data/docs/vendor/cache/fastimage-2.0.1.gem +0 -0
- data/docs/vendor/cache/ffi-1.9.14.gem +0 -0
- data/docs/vendor/cache/haml-4.0.7.gem +0 -0
- data/docs/vendor/cache/hamster-3.0.0.gem +0 -0
- data/docs/vendor/cache/hashie-3.4.6.gem +0 -0
- data/docs/vendor/cache/http_parser.rb-0.6.0.gem +0 -0
- data/docs/vendor/cache/i18n-0.7.0.gem +0 -0
- data/docs/vendor/cache/kramdown-1.13.2.gem +0 -0
- data/docs/vendor/cache/listen-3.0.8.gem +0 -0
- data/docs/vendor/cache/memoist-0.15.0.gem +0 -0
- data/docs/vendor/cache/middleman-4.2.0.gem +0 -0
- data/docs/vendor/cache/middleman-cli-4.2.0.gem +0 -0
- data/docs/vendor/cache/middleman-core-4.2.0.gem +0 -0
- data/docs/vendor/cache/middleman-gh-pages-0.3.1.gem +0 -0
- data/docs/vendor/cache/middleman-livereload-3.4.6.gem +0 -0
- data/docs/vendor/cache/minitest-5.10.1.gem +0 -0
- data/docs/vendor/cache/padrino-helpers-0.13.3.3.gem +0 -0
- data/docs/vendor/cache/padrino-support-0.13.3.3.gem +0 -0
- data/docs/vendor/cache/parallel-1.10.0.gem +0 -0
- data/docs/vendor/cache/public_suffix-2.0.5.gem +0 -0
- data/docs/vendor/cache/rack-2.0.1.gem +0 -0
- data/docs/vendor/cache/rack-livereload-0.3.16.gem +0 -0
- data/docs/vendor/cache/rake-12.0.0.gem +0 -0
- data/docs/vendor/cache/rb-fsevent-0.9.8.gem +0 -0
- data/docs/vendor/cache/rb-inotify-0.9.7.gem +0 -0
- data/docs/vendor/cache/sass-3.4.23.gem +0 -0
- data/docs/vendor/cache/servolux-0.12.0.gem +0 -0
- data/docs/vendor/cache/thor-0.19.4.gem +0 -0
- data/docs/vendor/cache/thread_safe-0.3.5.gem +0 -0
- data/docs/vendor/cache/tilt-2.0.5.gem +0 -0
- data/docs/vendor/cache/tzinfo-1.2.2.gem +0 -0
- data/docs/vendor/cache/uglifier-3.0.4.gem +0 -0
- data/lib/word_search.rb +25 -24
- data/lib/word_search/catalog.rb +1 -0
- data/lib/word_search/generator.rb +9 -3
- data/lib/word_search/generator/base.rb +50 -2
- data/lib/word_search/plane.rb +1 -0
- data/lib/word_search/plane/base.rb +25 -2
- data/lib/word_search/position_word/base.rb +32 -3
- data/lib/word_search/solver.rb +113 -3
- data/lib/word_search/three_dimensional/direction.rb +1 -0
- data/lib/word_search/three_dimensional/generator.rb +1 -18
- data/lib/word_search/three_dimensional/plane.rb +8 -1
- data/lib/word_search/three_dimensional/point.rb +5 -0
- data/lib/word_search/three_dimensional/position_word.rb +7 -0
- data/lib/word_search/two_dimensional/direction.rb +1 -0
- data/lib/word_search/two_dimensional/generator.rb +1 -18
- data/lib/word_search/two_dimensional/plane.rb +6 -1
- data/lib/word_search/two_dimensional/point.rb +5 -0
- data/lib/word_search/two_dimensional/position_word.rb +7 -0
- data/lib/word_search/version.rb +2 -1
- data/lib/word_search/word_bank.rb +4 -3
- data/vendor/cache/activemodel-5.0.1.gem +0 -0
- data/vendor/cache/activesupport-5.0.1.gem +0 -0
- data/vendor/cache/codeclimate-test-reporter-1.0.4.gem +0 -0
- data/vendor/cache/concurrent-ruby-1.0.4.gem +0 -0
- data/vendor/cache/metaclass-0.0.4.gem +0 -0
- data/vendor/cache/minitest-5.10.1.gem +0 -0
- data/vendor/cache/mocha-1.2.1.gem +0 -0
- data/vendor/cache/parser-2.3.3.1.gem +0 -0
- data/vendor/cache/rainbow-2.2.1.gem +0 -0
- data/vendor/cache/rake-12.0.0.gem +0 -0
- data/vendor/cache/rspec-core-3.5.4.gem +0 -0
- data/vendor/cache/rubocop-0.46.0.gem +0 -0
- data/vendor/cache/ruby-enum-0.6.0.gem +0 -0
- data/vendor/cache/unicode-display_width-1.1.2.gem +0 -0
- data/word_search.gemspec +23 -21
- metadata +91 -29
- data/docs/source/images/github-light.png +0 -0
- data/docs/source/images/github.png +0 -0
- data/docs/source/stylesheets/site.css.scss +0 -71
- data/lib/solution.rb +0 -67
- data/vendor/cache/activemodel-5.0.0.1.gem +0 -0
- data/vendor/cache/activesupport-5.0.0.1.gem +0 -0
- data/vendor/cache/codeclimate-test-reporter-0.6.0.gem +0 -0
- data/vendor/cache/concurrent-ruby-1.0.2.gem +0 -0
- data/vendor/cache/minitest-5.9.0.gem +0 -0
- data/vendor/cache/parser-2.3.1.2.gem +0 -0
- data/vendor/cache/rainbow-2.1.0.gem +0 -0
- data/vendor/cache/rake-10.5.0.gem +0 -0
- data/vendor/cache/rspec-core-3.5.2.gem +0 -0
- data/vendor/cache/rubocop-0.42.0.gem +0 -0
- data/vendor/cache/ruby-enum-0.5.0.gem +0 -0
- data/vendor/cache/unicode-display_width-1.1.0.gem +0 -0
@@ -1,28 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module WordSearch
|
2
3
|
class PositionWord
|
3
4
|
class Base
|
4
|
-
attr_accessor :plane, :word, :direction, :coordinate
|
5
|
+
attr_accessor :plane, :word, :direction, :coordinate, :positions
|
5
6
|
|
6
7
|
def initialize(plane, word, direction, coordinate)
|
7
8
|
@plane = plane
|
8
9
|
@word = word
|
9
10
|
@direction = direction
|
10
11
|
@coordinate = coordinate
|
12
|
+
@positions = {}
|
11
13
|
end
|
12
14
|
|
13
15
|
def perform
|
14
16
|
return false unless valid?
|
15
17
|
|
16
|
-
|
18
|
+
letters.each_with_index do |letter, index|
|
17
19
|
place_letter(letter)
|
20
|
+
document_position(letter, index)
|
18
21
|
update_coordinates
|
19
22
|
end
|
23
|
+
|
24
|
+
positions
|
20
25
|
end
|
21
26
|
|
22
27
|
def valid?
|
23
28
|
valid_coordinates? && valid_letters?
|
24
29
|
end
|
25
30
|
|
31
|
+
def place_letter
|
32
|
+
raise NotImplementedError
|
33
|
+
end
|
34
|
+
|
35
|
+
def update_coordinates
|
36
|
+
raise NotImplementedError
|
37
|
+
end
|
38
|
+
|
39
|
+
def positive_last_coordinates?
|
40
|
+
raise NotImplementedError
|
41
|
+
end
|
42
|
+
|
43
|
+
def last_coordinates_in_plane?
|
44
|
+
raise NotImplementedError
|
45
|
+
end
|
46
|
+
|
47
|
+
def letter_at
|
48
|
+
raise NotImplementedError
|
49
|
+
end
|
50
|
+
|
51
|
+
def document_position
|
52
|
+
raise NotImplementedError
|
53
|
+
end
|
54
|
+
|
26
55
|
private
|
27
56
|
|
28
57
|
def last_x
|
@@ -79,7 +108,7 @@ module WordSearch
|
|
79
108
|
end
|
80
109
|
|
81
110
|
def letters
|
82
|
-
@letters ||= word.split(
|
111
|
+
@letters ||= word.split("")
|
83
112
|
end
|
84
113
|
|
85
114
|
def x_at(position)
|
data/lib/word_search/solver.rb
CHANGED
@@ -1,17 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module WordSearch
|
2
3
|
class Solver
|
3
|
-
attr_accessor :script, :word_bank, :plane
|
4
|
+
attr_accessor :script, :word_bank, :plane, :failed
|
4
5
|
|
5
6
|
def initialize(script, word_list_file, plane_file)
|
6
7
|
@script = script
|
7
8
|
@word_bank = WordBank.new(word_list_file)
|
8
9
|
@plane = Plane.make_from_file(plane_file)
|
10
|
+
@failed = false
|
9
11
|
end
|
10
12
|
|
11
|
-
def
|
13
|
+
def perform
|
14
|
+
master_solutions # load master solutions so it doesn't effect benchmark
|
15
|
+
bm = benchmark_solution
|
16
|
+
|
17
|
+
return bm if !failed && solved?
|
18
|
+
|
19
|
+
"Word Search incorrectly solved"
|
20
|
+
end
|
21
|
+
|
22
|
+
def master_solutions
|
23
|
+
@master_solutions ||=
|
24
|
+
import_solutions(
|
25
|
+
if File.exist?("solution_#{plane.digest}")
|
26
|
+
File.read("solution_#{plane.digest}")
|
27
|
+
else
|
28
|
+
generate_master_solution
|
29
|
+
end
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def benchmark_solution
|
12
36
|
Benchmark.measure do
|
13
|
-
|
37
|
+
begin
|
38
|
+
users_solution
|
39
|
+
rescue
|
40
|
+
self.failed = true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def users_solution
|
46
|
+
@users_solution ||=
|
47
|
+
import_solutions(File.read(JSON.parse(`ruby #{script}`)))
|
48
|
+
end
|
49
|
+
|
50
|
+
def solved?
|
51
|
+
@word_bank.all? { |word| users_solution[word] == master_solutions[word] }
|
52
|
+
end
|
53
|
+
|
54
|
+
def import_solutions(solution_array)
|
55
|
+
solution_array.split("---").map do |positions|
|
56
|
+
{
|
57
|
+
positions.strip.split("\n").map(&:first).join =>
|
58
|
+
positions.strip.split("\n").map.with_index do |letter, index|
|
59
|
+
[index, JSON.parse(letter[2..-1])]
|
60
|
+
end.to_h
|
61
|
+
}
|
62
|
+
end.reduce({}, :merge)
|
63
|
+
end
|
64
|
+
|
65
|
+
def generate_master_solution
|
66
|
+
word_bank.map do |word|
|
67
|
+
find_word(word)
|
68
|
+
end.join("---")
|
69
|
+
end
|
70
|
+
|
71
|
+
def directions
|
72
|
+
@directions ||=
|
73
|
+
if plane.two_dimensional?
|
74
|
+
WordSearch::TwoDimensional::Direction
|
75
|
+
else
|
76
|
+
WordSearch::ThreeDimensional::Direction
|
77
|
+
end.values
|
78
|
+
end
|
79
|
+
|
80
|
+
def find_word(word)
|
81
|
+
string = ""
|
82
|
+
plane.catalog[word[0]].find do |point|
|
83
|
+
directions.find do |direction|
|
84
|
+
next if (spot = find_point(point, word.size - 1, direction)).blank? ||
|
85
|
+
not_found?(spot, word, point, direction)
|
86
|
+
|
87
|
+
string = letter_positions(word, direction, point)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
string
|
92
|
+
end
|
93
|
+
|
94
|
+
def letter_positions(word, direction, point)
|
95
|
+
solution = ""
|
96
|
+
word.split("").each_with_index do |letter, index|
|
97
|
+
solution += "#{letter} #{point.coordinate}\n"
|
98
|
+
next if index == (word.length - 1)
|
99
|
+
|
100
|
+
point = plane.find_next_point(point, direction)
|
101
|
+
end
|
102
|
+
|
103
|
+
solution
|
104
|
+
end
|
105
|
+
|
106
|
+
def not_found?(spot, word, point, direction)
|
107
|
+
!(spot.letter == word[-1] && double_check(word, point, direction))
|
108
|
+
end
|
109
|
+
|
110
|
+
def find_point(point, move, direction)
|
111
|
+
plane.dig(
|
112
|
+
point.x + (move * direction[0]),
|
113
|
+
point.y + (move * direction[1]),
|
114
|
+
)
|
115
|
+
end
|
116
|
+
|
117
|
+
def double_check(word, point, direction)
|
118
|
+
matching = true
|
119
|
+
|
120
|
+
(word.length - 2).times do |i|
|
121
|
+
matching &&= find_point(point, (1 + i), direction).letter == word[1 + i]
|
14
122
|
end
|
123
|
+
|
124
|
+
matching
|
15
125
|
end
|
16
126
|
end
|
17
127
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module WordSearch
|
2
3
|
module ThreeDimensional
|
3
4
|
class Generator < Generator::Base
|
@@ -9,24 +10,6 @@ module WordSearch
|
|
9
10
|
|
10
11
|
private
|
11
12
|
|
12
|
-
def place_word(word)
|
13
|
-
placed = false
|
14
|
-
until placed || used_coordinates.uniq.count == plane.total_points
|
15
|
-
placed = position_word(word).present?
|
16
|
-
end
|
17
|
-
|
18
|
-
word_bank.errors.add(word, 'cannot be placed') if placed.blank?
|
19
|
-
placed
|
20
|
-
end
|
21
|
-
|
22
|
-
def position_word(word)
|
23
|
-
used_coordinates << (coordinate = random_point)
|
24
|
-
|
25
|
-
directions.find do |direction|
|
26
|
-
PositionWord.new(plane, word, direction, coordinate).perform
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
13
|
def random_point
|
31
14
|
Point.new(random(plane.x), random(plane.y), random(plane.z))
|
32
15
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module WordSearch
|
2
3
|
module ThreeDimensional
|
3
4
|
class Plane < Plane::Base
|
@@ -53,6 +54,12 @@ module WordSearch
|
|
53
54
|
@directions ||= WordSearch::ThreeDimensional::Direction
|
54
55
|
end
|
55
56
|
|
57
|
+
def find_next_point(point, direction)
|
58
|
+
dig(
|
59
|
+
point.x + direction[0], point.y + direction[1], point.z + direction[2]
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
56
63
|
class << self
|
57
64
|
def make_from_file(file)
|
58
65
|
string = File.read(file).split("\n\n").map(&:split)
|
@@ -74,7 +81,7 @@ module WordSearch
|
|
74
81
|
|
75
82
|
string.each_with_index do |slice, z|
|
76
83
|
slice.reverse.each_with_index do |row, y|
|
77
|
-
row.split(
|
84
|
+
row.split("").each_with_index do |letter, x|
|
78
85
|
plane[x][y][z] = Point.new(x, y, z, letter)
|
79
86
|
add_to_catalog(plane, plane[x][y][z])
|
80
87
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module WordSearch
|
2
3
|
module ThreeDimensional
|
3
4
|
class PositionWord < PositionWord::Base
|
@@ -24,6 +25,12 @@ module WordSearch
|
|
24
25
|
def letter_at(position)
|
25
26
|
plane.dig(x_at(position), y_at(position), z_at(position)).letter
|
26
27
|
end
|
28
|
+
|
29
|
+
def document_position(letter, index)
|
30
|
+
positions.merge!("#{letter}-#{index}" => {
|
31
|
+
x: coordinate.x, y: coordinate.y, z: coordinate.z
|
32
|
+
})
|
33
|
+
end
|
27
34
|
end
|
28
35
|
end
|
29
36
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module WordSearch
|
2
3
|
module TwoDimensional
|
3
4
|
class Generator < Generator::Base
|
@@ -9,24 +10,6 @@ module WordSearch
|
|
9
10
|
|
10
11
|
private
|
11
12
|
|
12
|
-
def place_word(word)
|
13
|
-
placed = false
|
14
|
-
until placed || used_coordinates.uniq.count == plane.total_points
|
15
|
-
placed = position_word(word).present?
|
16
|
-
end
|
17
|
-
|
18
|
-
word_bank.errors.add(word, 'cannot be placed') if placed.blank?
|
19
|
-
placed
|
20
|
-
end
|
21
|
-
|
22
|
-
def position_word(word)
|
23
|
-
used_coordinates << (coordinate = random_point)
|
24
|
-
|
25
|
-
directions.find do |direction|
|
26
|
-
PositionWord.new(plane, word, direction, coordinate).perform
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
13
|
def random_point
|
31
14
|
Point.new(random(plane.x), random(plane.y))
|
32
15
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module WordSearch
|
2
3
|
module TwoDimensional
|
3
4
|
class Plane < Plane::Base
|
@@ -34,6 +35,10 @@ module WordSearch
|
|
34
35
|
@directions ||= WordSearch::TwoDimensional::Direction
|
35
36
|
end
|
36
37
|
|
38
|
+
def find_next_point(point, direction)
|
39
|
+
dig(point.x + direction[0], point.y + direction[1])
|
40
|
+
end
|
41
|
+
|
37
42
|
class << self
|
38
43
|
def make_from_file(file)
|
39
44
|
string = File.read(file).split("\n").reverse
|
@@ -50,7 +55,7 @@ module WordSearch
|
|
50
55
|
plane = new(x_len.first, string.count)
|
51
56
|
|
52
57
|
string.each_with_index do |row, y|
|
53
|
-
row.split(
|
58
|
+
row.split("").each_with_index do |letter, x|
|
54
59
|
add_to_catalog(plane, plane[x][y] = Point.new(x, y, letter))
|
55
60
|
end
|
56
61
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module WordSearch
|
2
3
|
module TwoDimensional
|
3
4
|
class PositionWord < PositionWord::Base
|
@@ -23,6 +24,12 @@ module WordSearch
|
|
23
24
|
def letter_at(position)
|
24
25
|
plane.dig(x_at(position), y_at(position)).letter
|
25
26
|
end
|
27
|
+
|
28
|
+
def document_position(letter, index)
|
29
|
+
positions.merge!("#{letter}-#{index}" => {
|
30
|
+
x: coordinate.x, y: coordinate.y
|
31
|
+
})
|
32
|
+
end
|
26
33
|
end
|
27
34
|
end
|
28
35
|
end
|
data/lib/word_search/version.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module WordSearch
|
2
3
|
class WordBank < Array
|
3
4
|
include ActiveModel::Validations
|
@@ -30,15 +31,15 @@ module WordSearch
|
|
30
31
|
private
|
31
32
|
|
32
33
|
def word_bank
|
33
|
-
errors.add(:base,
|
34
|
+
errors.add(:base, "Word bank cannot be empty") if blank?
|
34
35
|
end
|
35
36
|
|
36
37
|
def valid_file?(file)
|
37
|
-
File.file?(file) && File.extname(file) ==
|
38
|
+
File.file?(file) && File.extname(file) == ".csv"
|
38
39
|
end
|
39
40
|
|
40
41
|
def invalid_file
|
41
|
-
errors.add(:file,
|
42
|
+
errors.add(:file, "is invalid")
|
42
43
|
false
|
43
44
|
end
|
44
45
|
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|