word_search 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +3 -1
- data/docs/source/index.html.haml +3 -0
- data/lib/word_search/generator/base.rb +0 -13
- data/lib/word_search/generator.rb +0 -1
- data/lib/word_search/plane/base.rb +4 -4
- data/lib/word_search/plane.rb +7 -4
- data/lib/word_search/solver.rb +42 -82
- data/lib/word_search/three_dimensional/plane.rb +7 -5
- data/lib/word_search/two_dimensional/plane.rb +9 -5
- data/lib/word_search/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7bc57d355737b67f6e08e5b58dabe5a891328f3b
|
4
|
+
data.tar.gz: 9314298eb080b5b5a5496e9cde14168b76bd4d81
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b12c07d549111243d9692fdc87dc2adefaf036b26619e112d49cdc98e580bfc99ec153e3dafb3dadc05f8d71184481769eb733d12896532e80b7d76581294759
|
7
|
+
data.tar.gz: afea61baebcb38d02ac8dc0e4c5e4ee23f41d450c00d9e02cb33b515a836ca3835f4a887ebaa24625f14cc7957ae87c1772cd1e2bb77e616f8134806a849c5a1
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -69,7 +69,9 @@ To solve or benchmark your solution script:
|
|
69
69
|
=> #<Benchmark::Tms:0x007fd722cc6b58 @cstime=0.07, @cutime=0.44, @label="", @real=0.5259899999946356, @stime=0.0, @total=0.51, @utime=0.0>
|
70
70
|
```
|
71
71
|
_NOTE_: Your script should be an executable ruby script that writes the location
|
72
|
-
of each letter to a file in the following format and returns the file path
|
72
|
+
of each letter to a file in the following format and returns the file path. Your
|
73
|
+
script should also accept command line arguments the first being the plane file
|
74
|
+
the second being the word list file.
|
73
75
|
```
|
74
76
|
h [4, 9]
|
75
77
|
e [5, 9]
|
data/docs/source/index.html.haml
CHANGED
@@ -94,7 +94,10 @@ title: Word Search Gem
|
|
94
94
|
You can benchmark and check if your solution works by using the Solver class.
|
95
95
|
Your script should be an executable ruby script that writes the location
|
96
96
|
of each letter to a file in the following format and returns the file path.
|
97
|
+
It should also be able to accept command line arguments for the plane file
|
98
|
+
and the words file, in that order.
|
97
99
|
%pre
|
100
|
+
|
98
101
|
:preserve
|
99
102
|
h [4, 9]
|
100
103
|
e [5, 9]
|
@@ -24,19 +24,6 @@ module WordSearch
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
def write_solution
|
28
|
-
file_name = "solution_#{plane.digest}"
|
29
|
-
File.open(file_name, "w") do |f|
|
30
|
-
solution = positions.map do |_word, letter_positions|
|
31
|
-
letter_positions.map do |letter, position|
|
32
|
-
"#{letter.split('-')[0]} #{position.values}"
|
33
|
-
end.join("\n")
|
34
|
-
end.join("\n---\n")
|
35
|
-
|
36
|
-
f.write solution
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
27
|
private
|
41
28
|
|
42
29
|
def place_word(word)
|
@@ -38,10 +38,6 @@ module WordSearch
|
|
38
38
|
puts to_s
|
39
39
|
end
|
40
40
|
|
41
|
-
def digest
|
42
|
-
Digest::MD5.hexdigest(to_s)
|
43
|
-
end
|
44
|
-
|
45
41
|
def to_s
|
46
42
|
raise NotImplementedError
|
47
43
|
end
|
@@ -58,6 +54,10 @@ module WordSearch
|
|
58
54
|
raise NotImplementedError
|
59
55
|
end
|
60
56
|
|
57
|
+
def letter_at(*positions)
|
58
|
+
dig(*positions)
|
59
|
+
end
|
60
|
+
|
61
61
|
private
|
62
62
|
|
63
63
|
def initialize_plane
|
data/lib/word_search/plane.rb
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module WordSearch
|
3
3
|
class Plane < SimpleDelegator
|
4
|
-
def self.make_from_file(file)
|
5
|
-
|
4
|
+
def self.make_from_file(file, should_catalog: true)
|
5
|
+
dimension =
|
6
6
|
if File.read(file).split("\n\n").count > 1
|
7
|
-
ThreeDimensional
|
7
|
+
ThreeDimensional
|
8
8
|
else
|
9
|
-
TwoDimensional
|
9
|
+
TwoDimensional
|
10
10
|
end
|
11
11
|
|
12
|
+
obj =
|
13
|
+
dimension::Plane.make_from_file(file, should_catalog: should_catalog)
|
14
|
+
|
12
15
|
new(obj)
|
13
16
|
end
|
14
17
|
|
data/lib/word_search/solver.rb
CHANGED
@@ -1,33 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module WordSearch
|
3
3
|
class Solver
|
4
|
-
attr_accessor :script, :word_bank, :plane, :failed
|
4
|
+
attr_accessor :script, :word_bank, :plane, :failed, :benchmark,
|
5
|
+
:word_list_file, :plane_file
|
5
6
|
|
6
7
|
def initialize(script, word_list_file, plane_file)
|
7
|
-
@script
|
8
|
-
@
|
9
|
-
@
|
10
|
-
@
|
8
|
+
@script = script
|
9
|
+
@word_list_file = word_list_file
|
10
|
+
@word_bank = WordBank.new(word_list_file)
|
11
|
+
@plane_file = plane_file
|
12
|
+
@plane = Plane.make_from_file(plane_file, should_catalog: false)
|
13
|
+
@failed = false
|
11
14
|
end
|
12
15
|
|
13
16
|
def perform
|
14
|
-
|
17
|
+
return if script.blank?
|
15
18
|
bm = benchmark_solution
|
16
19
|
|
17
|
-
return bm if !failed && solved?
|
20
|
+
return(@benchmark = bm) if !failed && solved?
|
18
21
|
|
19
22
|
"Word Search incorrectly solved"
|
20
23
|
end
|
21
24
|
|
22
|
-
def
|
23
|
-
@
|
24
|
-
|
25
|
-
|
26
|
-
File.read("solution_#{plane.digest}")
|
27
|
-
else
|
28
|
-
generate_master_solution
|
29
|
-
end
|
30
|
-
)
|
25
|
+
def solved?
|
26
|
+
@word_bank.all? do |word|
|
27
|
+
correctly_found?(word, users_solution[word])
|
28
|
+
end && proper_direction?
|
31
29
|
end
|
32
30
|
|
33
31
|
private
|
@@ -43,12 +41,36 @@ module WordSearch
|
|
43
41
|
end
|
44
42
|
|
45
43
|
def users_solution
|
46
|
-
@users_solution ||=
|
47
|
-
|
44
|
+
@users_solution ||= import_solutions(File.read(JSON.parse(
|
45
|
+
`ruby #{script} #{plane_file} #{word_list_file}`
|
46
|
+
)))
|
48
47
|
end
|
49
48
|
|
50
|
-
def
|
51
|
-
|
49
|
+
def correctly_found?(word, positions)
|
50
|
+
word.split("").map.with_index do |letter, index|
|
51
|
+
plane.letter_at(*positions[index]).letter == letter
|
52
|
+
end.inject(:&)
|
53
|
+
end
|
54
|
+
|
55
|
+
def proper_direction?
|
56
|
+
users_solution.all? do |word, positions|
|
57
|
+
values = positions.values
|
58
|
+
direction = reduce_direction(values.pop.zip(*values), word)
|
59
|
+
plane.directions.values.include?(direction)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def reduce_direction(values, word)
|
64
|
+
values.map do |direction|
|
65
|
+
gcd = direction.reduce(:gcd)
|
66
|
+
direction.map { |coord| coord / gcd }.uniq
|
67
|
+
end.map do |direction|
|
68
|
+
if (direction = direction.inject(:-)).gcd(word.length) == word.length
|
69
|
+
direction / word.length
|
70
|
+
else
|
71
|
+
direction
|
72
|
+
end
|
73
|
+
end
|
52
74
|
end
|
53
75
|
|
54
76
|
def import_solutions(solution_array)
|
@@ -61,67 +83,5 @@ module WordSearch
|
|
61
83
|
}
|
62
84
|
end.reduce({}, :merge)
|
63
85
|
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]
|
122
|
-
end
|
123
|
-
|
124
|
-
matching
|
125
|
-
end
|
126
86
|
end
|
127
87
|
end
|
@@ -61,12 +61,12 @@ module WordSearch
|
|
61
61
|
end
|
62
62
|
|
63
63
|
class << self
|
64
|
-
def make_from_file(file)
|
64
|
+
def make_from_file(file, should_catalog: true)
|
65
65
|
string = File.read(file).split("\n\n").map(&:split)
|
66
66
|
|
67
67
|
return false unless valid_file?(string)
|
68
68
|
|
69
|
-
make_word_search(string)
|
69
|
+
make_word_search(string, should_catalog: should_catalog)
|
70
70
|
end
|
71
71
|
|
72
72
|
private
|
@@ -76,14 +76,14 @@ module WordSearch
|
|
76
76
|
string.flat_map { |row| row.map(&:length) }.uniq.count == 1
|
77
77
|
end
|
78
78
|
|
79
|
-
def make_word_search(string)
|
79
|
+
def make_word_search(string, should_catalog: true)
|
80
80
|
plane = empty_3d_plane_from_string(string)
|
81
81
|
|
82
82
|
string.each_with_index do |slice, z|
|
83
83
|
slice.reverse.each_with_index do |row, y|
|
84
84
|
row.split("").each_with_index do |letter, x|
|
85
85
|
plane[x][y][z] = Point.new(x, y, z, letter)
|
86
|
-
add_to_catalog(plane, plane[x][y][z])
|
86
|
+
add_to_catalog(plane, plane[x][y][z], should_catalog)
|
87
87
|
end
|
88
88
|
end
|
89
89
|
end
|
@@ -97,7 +97,9 @@ module WordSearch
|
|
97
97
|
new(x, y, string.count)
|
98
98
|
end
|
99
99
|
|
100
|
-
def add_to_catalog(plane, point)
|
100
|
+
def add_to_catalog(plane, point, should_catalog = true)
|
101
|
+
return unless should_catalog
|
102
|
+
|
101
103
|
plane.catalog[point.letter] ||= []
|
102
104
|
plane.catalog[point.letter] << point
|
103
105
|
end
|
@@ -40,30 +40,34 @@ module WordSearch
|
|
40
40
|
end
|
41
41
|
|
42
42
|
class << self
|
43
|
-
def make_from_file(file)
|
43
|
+
def make_from_file(file, should_catalog: true)
|
44
44
|
string = File.read(file).split("\n").reverse
|
45
45
|
|
46
46
|
return false if (x_len = string.collect(&:length).uniq).count > 1 ||
|
47
47
|
x_len.blank?
|
48
48
|
|
49
|
-
make_word_search(x_len, string)
|
49
|
+
make_word_search(x_len, string, should_catalog: should_catalog)
|
50
50
|
end
|
51
51
|
|
52
52
|
private
|
53
53
|
|
54
|
-
def make_word_search(x_len, string)
|
54
|
+
def make_word_search(x_len, string, should_catalog: true)
|
55
55
|
plane = new(x_len.first, string.count)
|
56
56
|
|
57
57
|
string.each_with_index do |row, y|
|
58
58
|
row.split("").each_with_index do |letter, x|
|
59
|
-
add_to_catalog(
|
59
|
+
add_to_catalog(
|
60
|
+
plane, plane[x][y] = Point.new(x, y, letter), should_catalog
|
61
|
+
)
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
63
65
|
plane
|
64
66
|
end
|
65
67
|
|
66
|
-
def add_to_catalog(plane, point)
|
68
|
+
def add_to_catalog(plane, point, should_catalog = true)
|
69
|
+
return unless should_catalog
|
70
|
+
|
67
71
|
plane.catalog[point.letter] ||= []
|
68
72
|
plane.catalog[point.letter] << point
|
69
73
|
end
|
data/lib/word_search/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: word_search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- npezza93
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|