maze-solver 1.0.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.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # encoding: UTF-8
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ gem 'rake'
8
+ gem 'rspec'
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Pete Johns
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,48 @@
1
+ # Maze Solver
2
+
3
+ Written as an exercise in applying Ruby, this project solves mazes:
4
+
5
+ maze-solver etc/demo.maze 18 0 38 0
6
+ About to solve your 40x14 maze from (18, 0) to (38,0).
7
+ GO!
8
+ Solved!
9
+ ******************.*******************.*
10
+ * .......****.** .......****.*
11
+ * *****.*****...**.** *****.*****...**.*
12
+ * *****.*******.**.** *****.*******.**.*
13
+ * * ......**.**.** * ......**.**.*
14
+ * **********.**....** **********.**....*
15
+ ************.*******************.*******
16
+ ************.***** *************.***** *
17
+ * ..****............... **** *
18
+ * ***** *****...**.** ***** ***** ** *
19
+ * ***** *******.**.** ***** ******* ** *
20
+ * * **.**.** * ** ** *
21
+ * ********** **....** ********** ** *
22
+ ****************************************
23
+
24
+
25
+ ## Installation
26
+
27
+ $ gem install maze-solver
28
+
29
+ ## Usage
30
+
31
+ maze-solver filename start_x start_y end_x end_y
32
+
33
+ ## Contributing
34
+
35
+ 1. Fork it
36
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
37
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
38
+ 4. Push to the branch (`git push origin my-new-feature`)
39
+ 5. Create new Pull Request
40
+
41
+ ## Thanks
42
+
43
+ If you find this stuff useful, please follow this repository on
44
+ [GitHub](https://github.com/johnsyweb/ruby_maze_solver). If you have something to say,
45
+ you can contact [johnsyweb](http://johnsy.com/about/) on
46
+ [Twitter](http://twitter.com/johnsyweb/) and
47
+ [GitHub](https://github.com/johnsyweb/).
48
+
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new("spec")
5
+
6
+ task :default => :spec
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'maze_solver'
7
+
8
+ def main(filename, start_x, start_y, end_x, end_y)
9
+ maze = MazeSolver::MazeSolver.new(from_file: filename)
10
+ puts "About to solve your #{maze.width}x#{maze.height} maze from " +
11
+ "(#{start_x}, #{start_y}) to (#{end_x},#{end_y})."
12
+ puts 'GO!'
13
+ if maze.solve start_x.to_i, start_y.to_i, end_x.to_i, end_y.to_i
14
+ puts 'Solved!'
15
+ else
16
+ puts 'You beat me!'
17
+ end
18
+ puts maze
19
+ end
20
+
21
+ if ARGV.length == 5
22
+ filename, start_x, start_y, end_x, end_y = ARGV
23
+ main(filename, start_x, start_y, end_x, end_y)
24
+ else
25
+ puts "Usage: #{$PROGRAM_NAME} filename start_x start_y end_x end_y\n"
26
+ puts "Example: #{$PROGRAM_NAME} demo.maze 18 0 38 0\n"
27
+ end
@@ -0,0 +1,14 @@
1
+ ****************** ******************* *
2
+ * **** ** **** *
3
+ * ***** ***** ** ** ***** ***** ** *
4
+ * ***** ******* ** ** ***** ******* ** *
5
+ * * ** ** ** * ** ** *
6
+ * ********** ** ** ********** ** *
7
+ ************ ******************* *******
8
+ ************ ***** ************* ***** *
9
+ * **** **** *
10
+ * ***** ***** ** ** ***** ***** ** *
11
+ * ***** ******* ** ** ***** ******* ** *
12
+ * * ** ** ** * ** ** *
13
+ * ********** ** ** ********** ** *
14
+ ****************************************
@@ -0,0 +1,74 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'maze_solver/version'
4
+
5
+ module MazeSolver
6
+
7
+ class MazeSolver
8
+
9
+ def initialize(args = {})
10
+ if args[:from_grid]
11
+ @grid = args[:from_grid].split("\n")
12
+ elsif args[:from_file]
13
+ @grid = from_file(args[:from_file])
14
+ end
15
+ end
16
+
17
+ def height
18
+ @grid.size
19
+ end
20
+
21
+ def width
22
+ @grid.map { |row| row.length }.max
23
+ end
24
+
25
+ def visitable?(x, y)
26
+ row, column = y, x
27
+ return false unless (0...height).include? row
28
+ return false unless (0...width).include? column
29
+ @grid[row][column].chr == ' '
30
+ end
31
+
32
+ def visit(x, y)
33
+ row, column = y, x
34
+ @grid[row][column] = '.'
35
+ end
36
+
37
+ def unvisit(x, y)
38
+ row, column = y, x
39
+ @grid[row][column] = ' '
40
+ end
41
+
42
+ def solve(start_x, start_y, end_x, end_y)
43
+ return false unless visitable?(start_x, start_y)
44
+
45
+ visit start_x, start_y
46
+
47
+ return true if [start_x, start_y] == [end_x, end_y]
48
+
49
+ return true if adjacent_cell_solvable?(start_x, start_y, end_x, end_y)
50
+
51
+ unvisit(start_x, start_y)
52
+
53
+ false
54
+ end
55
+
56
+ def adjacent_cell_solvable?(start_x, start_y, end_x, end_y)
57
+ solve(start_x + 1, start_y, end_x, end_y) ||
58
+ solve(start_x, start_y + 1, end_x, end_y) ||
59
+ solve(start_x - 1, start_y, end_x, end_y) ||
60
+ solve(start_x, start_y - 1, end_x, end_y)
61
+ end
62
+
63
+ def to_s
64
+ @grid.join("\n")
65
+ end
66
+
67
+ def from_file(filename)
68
+ @grid = File.open(filename, 'r').readlines
69
+ @grid.each { | row | row.strip! }
70
+ end
71
+
72
+ end
73
+
74
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: UTF-8
2
+
3
+ module MazeSolver
4
+ VERSION = '1.0.0'
5
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: UTF-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'maze_solver/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = 'maze-solver'
8
+ gem.version = MazeSolver::VERSION
9
+ gem.authors = ['Pete Johns']
10
+ gem.email = ['paj-github@johnsy.com']
11
+ gem.description = 'A gem to solve a 2D maze.'
12
+ gem.summary = 'Written as an exercise'
13
+ gem.homepage = 'https://github.com/johnsyweb/ruby_maze_solver#readme'
14
+
15
+ gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ['lib']
19
+ end
@@ -0,0 +1,106 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe MazeSolver do
6
+ def given_a_simple_8_x_3_maze
7
+ @maze = MazeSolver::MazeSolver.new(from_grid: "********\n" +
8
+ " \n" +
9
+ "********\n"
10
+ )
11
+ end
12
+
13
+ it 'should have a width of 8' do
14
+ given_a_simple_8_x_3_maze
15
+ @maze.width.should eq 8
16
+ end
17
+
18
+ it 'should have a height of 3' do
19
+ given_a_simple_8_x_3_maze
20
+ @maze.height.should eq 3
21
+ end
22
+
23
+ it 'should be possible to visit an empty space' do
24
+ given_a_simple_8_x_3_maze
25
+ @maze.visitable?(0, 1).should be_true
26
+ end
27
+
28
+ it 'should not be possible to visit a wall' do
29
+ given_a_simple_8_x_3_maze
30
+ @maze.visitable?(0, 0).should be_false
31
+ end
32
+
33
+ it 'should not be possible to visit outside the maze' do
34
+ given_a_simple_8_x_3_maze
35
+ @maze.visitable?(8, 3).should be_false
36
+ end
37
+
38
+ it 'should not be possible to visit a visited space' do
39
+ given_a_simple_8_x_3_maze
40
+ @maze.visit 0, 1
41
+ @maze.visitable?(0, 1).should be_false
42
+ end
43
+
44
+ it 'should be possible to visit an unvisited space' do
45
+ given_a_simple_8_x_3_maze
46
+ @maze.visit 0, 1
47
+ @maze.unvisit 0, 1
48
+ @maze.visitable?(0, 1).should be_true
49
+ end
50
+
51
+ it 'should solve a simple maze' do
52
+ given_a_simple_8_x_3_maze
53
+ @maze.solve(0, 1, 7, 1).should be_true
54
+ end
55
+
56
+ it 'should solve a simple maze backwards' do
57
+ given_a_simple_8_x_3_maze
58
+ @maze.solve(7, 1, 0, 1).should be_true
59
+ end
60
+
61
+ it 'should solve a bigger maze' do
62
+ maze = MazeSolver::MazeSolver.new(from_grid: "********\n" +
63
+ " ** *\n" +
64
+ "* ** * *\n" +
65
+ "* * * *\n" +
66
+ "* ** * *\n" +
67
+ "* **** *\n" +
68
+ "* *\n" +
69
+ "********\n")
70
+ maze.solve(0, 1, 3, 3).should be_true
71
+ end
72
+
73
+ it 'should fail an impossible maze' do
74
+ maze = MazeSolver::MazeSolver.new(from_grid: "********\n" +
75
+ " ** *\n" +
76
+ "* **** *\n" +
77
+ "* * * *\n" +
78
+ "* ** * *\n" +
79
+ "* **** *\n" +
80
+ "* *\n" +
81
+ "********\n")
82
+ maze.solve(0, 1, 3, 3).should be_false
83
+ end
84
+
85
+ it 'should be printable' do
86
+ given_a_simple_8_x_3_maze
87
+ @maze.to_s.should eq "********\n" +
88
+ " \n" +
89
+ '********'
90
+ end
91
+
92
+ it 'should be printable when solved' do
93
+ given_a_simple_8_x_3_maze
94
+ @maze.solve 0, 1, 7, 1
95
+ @maze.to_s.should eq "********\n" +
96
+ "........\n" +
97
+ '********'
98
+ end
99
+
100
+ it 'should be creatable from a file' do
101
+ maze = MazeSolver::MazeSolver.new(from_file: 'spec/test.maze')
102
+ maze.solve(18, 0, 12, 6).should be_true
103
+ end
104
+
105
+ end
106
+
@@ -0,0 +1,12 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+ require 'maze_solver'
6
+
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+ config.order = 'random'
12
+ end
@@ -0,0 +1,7 @@
1
+ ****************** *
2
+ * * **** *
3
+ * ***** ***** ** *
4
+ * ***** ******* ** *
5
+ * * ** ** *
6
+ * ********** ** *
7
+ ************ *******
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: maze-solver
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Pete Johns
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-19 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A gem to solve a 2D maze.
15
+ email:
16
+ - paj-github@johnsy.com
17
+ executables:
18
+ - maze-solver
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - .rspec
24
+ - Gemfile
25
+ - LICENSE.txt
26
+ - README.md
27
+ - Rakefile
28
+ - bin/maze-solver
29
+ - etc/demo.maze
30
+ - lib/maze_solver.rb
31
+ - lib/maze_solver/version.rb
32
+ - maze_solver.gemspec
33
+ - spec/maze_spec.rb
34
+ - spec/spec_helper.rb
35
+ - spec/test.maze
36
+ homepage: https://github.com/johnsyweb/ruby_maze_solver#readme
37
+ licenses: []
38
+ post_install_message:
39
+ rdoc_options: []
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubyforge_project:
56
+ rubygems_version: 1.8.23
57
+ signing_key:
58
+ specification_version: 3
59
+ summary: Written as an exercise
60
+ test_files:
61
+ - spec/maze_spec.rb
62
+ - spec/spec_helper.rb
63
+ - spec/test.maze