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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d6966dcbd25d6689f540841bbc311906cd8fb7c9
4
- data.tar.gz: b4764a2f5ab6996c09ec7fc9a8a37c3d3c5b22a5
3
+ metadata.gz: 7bc57d355737b67f6e08e5b58dabe5a891328f3b
4
+ data.tar.gz: 9314298eb080b5b5a5496e9cde14168b76bd4d81
5
5
  SHA512:
6
- metadata.gz: db068f3c4cd0f2c12f9612e32bdbca5d81ab479ea7e89d4dc88e9d458ba2bfdf96f08bd9bc25a623f9e37604a58641d65b3144f8c021415590ba73fa9dfe47f1
7
- data.tar.gz: 94de5566fe37d9ac130b85f5edbc16e3ceeaeb168e4b0e92f201b7d4db4368d282ae9b4de613b026f4740c6117cf858108a50c25e9446f416497d361e941cc88
6
+ metadata.gz: b12c07d549111243d9692fdc87dc2adefaf036b26619e112d49cdc98e580bfc99ec153e3dafb3dadc05f8d71184481769eb733d12896532e80b7d76581294759
7
+ data.tar.gz: afea61baebcb38d02ac8dc0e4c5e4ee23f41d450c00d9e02cb33b515a836ca3835f4a887ebaa24625f14cc7957ae87c1772cd1e2bb77e616f8134806a849c5a1
data/.gitignore CHANGED
@@ -13,3 +13,4 @@
13
13
  /docs/.sass-cache
14
14
  /docs/build
15
15
  solution_*
16
+ /solution/
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]
@@ -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)
@@ -24,7 +24,6 @@ module WordSearch
24
24
 
25
25
  if valid?
26
26
  plane.add_letters
27
- write_solution
28
27
  plane
29
28
  else
30
29
  false
@@ -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
@@ -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
- obj =
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::Plane.make_from_file(file)
7
+ ThreeDimensional
8
8
  else
9
- TwoDimensional::Plane.make_from_file(file)
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
 
@@ -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 = script
8
- @word_bank = WordBank.new(word_list_file)
9
- @plane = Plane.make_from_file(plane_file)
10
- @failed = false
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
- master_solutions # load master solutions so it doesn't effect benchmark
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 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
- )
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
- import_solutions(File.read(JSON.parse(`ruby #{script}`)))
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 solved?
51
- @word_bank.all? { |word| users_solution[word] == master_solutions[word] }
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(plane, plane[x][y] = Point.new(x, y, letter))
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
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module WordSearch
3
- VERSION = "1.0.1"
3
+ VERSION = "1.1.0"
4
4
  end
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.1
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-09 00:00:00.000000000 Z
11
+ date: 2017-01-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport