word_search 1.0.1 → 1.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 +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
|