nasa_rovers 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: bde9963aec22cee7e62520420adf36418152e750fcae772b460ffb66f366a0b5
4
+ data.tar.gz: ceb0fd9641e1d3fd48b8eff336033281bbc1681077894827439fbc4e46ee29f4
5
+ SHA512:
6
+ metadata.gz: 112a7da8ac2e1a06b0db42aa6af6188ab4b2bc58b4ea55bd14f9aad5bb4199c730462644304ce87c36a24685d1be6e08f1848587c520ccace279bd95b1395bb7
7
+ data.tar.gz: 73687811157685f0bf75e0c78575c304779b6f369a348706fe5893d329d7ec0d4c673eeb14eddeae3368d4eb31e2baee70b0b92c7f1f8a0cf4c814613f0ec32f
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ Gemfile.lock
2
+ *.gem
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.5.3
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ - 2.4.0
6
+ - 2.5.3
7
+ before_install: gem install bundler -v 1.17.1
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in nasa_rovers.gemspec
4
+ gemspec
data/OBJECTIVES.md ADDED
@@ -0,0 +1,41 @@
1
+ ## Table of Contents
2
+ * [Summary](#summary)
3
+
4
+ ## Summary
5
+ A squad of robotic rovers are to be landed by NASA on a plateau on Mars. This plateau, which is curiously rectangular, must be navigated by the rovers so that their on-board cameras can get a complete view of the surrounding terrain to send back to Earth.
6
+ A rover's position and location is represented by a combination of x and y coordinates and a letter representing one of the four cardinal compass points. The plateau is divided up into a grid to simplify navigation.
7
+
8
+ An example position might be `0, 0, N`, which means the rover is in the bottom left corner and facing North.
9
+
10
+ In order to control a rover, NASA sends a simple string of letters. The possible letters are `L`, `R` and `M`. `L` and `R` makes the rover spin 90 degrees left or right respectively, without moving from its current spot. `M` means move forward one grid point, and maintain the same heading.
11
+
12
+ Assume that the square directly North from (x, y) is (x, y+1).
13
+
14
+ ### Input
15
+ The first line of input is the upper-right coordinates of the plateau, the lower-left coordinates are assumed to be `0,0`.
16
+
17
+ The rest of the input is information pertaining to the rovers that have been deployed. Each rover has two lines of input. The first line gives the rover's position, and the second line is a series of instructions telling the rover how to explore the plateau.
18
+
19
+ The position is made up of two integers and a letter separated by spaces, corresponding to the x and y co-ordinates and the rover's orientation.
20
+
21
+ Each rover will be finished sequentially, which means that the second rover won't start to move until the first one has finished moving.
22
+
23
+ ### Output
24
+ The output for each rover should be its final co-ordinates and heading.
25
+
26
+ ### Input and Output
27
+
28
+ #### Test Input
29
+ ```
30
+ 5 5
31
+ 1 2 N
32
+ LMLMLMLMM
33
+ 3 3 E
34
+ MMRMMRMRRM
35
+ ```
36
+
37
+ #### Expected Output
38
+ ```
39
+ 1 3 N
40
+ 5 1 E
41
+ ```
data/README.md ADDED
@@ -0,0 +1,81 @@
1
+ ## Table of Contents
2
+ * [Scope](#scope)
3
+ * [Design](#design)
4
+ * [Footprint](#footprint)
5
+ * [SRP](#srp)
6
+ * [Test](#test)
7
+ * [Usage](#usage)
8
+ * [Library](#library)
9
+ * [CLI](#cli)
10
+
11
+ ## Scope
12
+ This gem is the Ruby implementation of the for the [NASA rovers](https://github.com/costajob/nasa_rovers/blob/master/OBJECTIVES.md) code kata.
13
+
14
+ ## Design
15
+
16
+ ### Footprint
17
+ The code keeps a minimal footprint, relying on standard library only and reducing it to its minimum (i.e. `optparse` was overkill for the simple CLI interface).
18
+
19
+ ### SRP
20
+ The code design follows the single responsibility principle by using a dedicated class for any specific task.
21
+
22
+ ### Test
23
+ The code is covered by fast, isolated unit testing, implemented by `minitest` spec (a standard, faster and as same as powerful alternative to `rspec`).
24
+ To run tests just execute rake:
25
+
26
+ ```shell
27
+ bundle exec rake
28
+ Run options: --seed 4303
29
+
30
+ # Running:
31
+
32
+ .....................
33
+
34
+ Finished in 0.004475s, 4692.7374 runs/s, 7374.3017 assertions/s.
35
+ ```
36
+
37
+ ## Usage
38
+
39
+ ### Library
40
+ Just execute the `bundle console` command and pass an array of instructions to the `Rover.instruct` method:
41
+
42
+ ```ruby
43
+ nasa_data = ["5 5", "1 2 N", "LMLMLMLMM", "3 3 E", "MMRMMRMRRM"]
44
+ puts NasaRovers::Rover.instruct(nasa_data)
45
+ #1 3 N
46
+ #5 1 E
47
+ #=> nil
48
+ ```
49
+
50
+ ### CLI
51
+ The library provides a CLI interface via the `nasa_rovers` command from the terminal.
52
+
53
+ #### Help
54
+ You can print CLI help by:
55
+
56
+ ```shell
57
+ $ ./bin/nasa_rovers -h
58
+ Usage: nasa_rovers ./nasa_data.txt
59
+ -h --help Print this help
60
+ <path-to-file> Instruct rovers with NASA data
61
+ ```
62
+
63
+ #### Input
64
+ The program accepts as input a file containing the NASA data (for more info check ``SUMMARY.md`)
65
+
66
+ ```txt
67
+ # ./nasa_data.txt
68
+ 5 5
69
+ 1 2 N
70
+ LMLMLMLMM
71
+ 3 3 E
72
+ MMRMMRMRRM
73
+ ```
74
+
75
+ Just pass the file path to the program:
76
+
77
+ ```shell
78
+ $ ./bin/nasa_rovers ./nasa_data.txt
79
+ 1 3 N
80
+ 5 1 E
81
+ ```
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:spec) do |t|
5
+ t.libs << "spec"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["spec/**/*_spec.rb"]
8
+ end
9
+
10
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "nasa_rovers"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/nasa_rovers ADDED
@@ -0,0 +1,9 @@
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 "nasa_rovers"
7
+
8
+ input = ARGV.fetch(0, "")
9
+ NasaRovers::CLI.new(input).call
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,11 @@
1
+ require "nasa_rovers/cli"
2
+ require "nasa_rovers/coord"
3
+ require "nasa_rovers/plateau"
4
+ require "nasa_rovers/position"
5
+ require "nasa_rovers/rover"
6
+
7
+ module NasaRovers
8
+ extend self
9
+
10
+ CARDINALS = %w[N E S W]
11
+ end
@@ -0,0 +1,41 @@
1
+ require "nasa_rovers/rover"
2
+
3
+ module NasaRovers
4
+ class CLI
5
+ HELP_FLAGS = %w[-h --help]
6
+ COL_WIDTH = 23
7
+
8
+ def initialize(input, pipe=STDOUT, rover_class=Rover)
9
+ @input = input
10
+ @pipe = pipe
11
+ @rover = rover_class
12
+ end
13
+
14
+ def call
15
+ @pipe.puts output
16
+ end
17
+
18
+ private def output
19
+ return help if help?
20
+ return unless file?
21
+ data = File.readlines(@input).map(&:strip)
22
+ @rover.instruct(data)
23
+ end
24
+
25
+ private def file?
26
+ File.file?(File.expand_path(@input))
27
+ end
28
+
29
+ private def help?
30
+ HELP_FLAGS.include?(@input)
31
+ end
32
+
33
+ private def help
34
+ [].tap do |h|
35
+ h << %q{Usage: nasa_rovers ~/nasa_data.txt}
36
+ h << " %-#{COL_WIDTH}s Print this help" % "-h --help"
37
+ h << " %-#{COL_WIDTH}s Instruct rovers with NASA data" % "<path-to-file>"
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,33 @@
1
+ module NasaRovers
2
+ class Coord
3
+ def self.origin
4
+ @origin ||= new(0, 0)
5
+ end
6
+
7
+ def self.factory(data)
8
+ new(*data.split(" "))
9
+ end
10
+
11
+ attr_accessor :x, :y
12
+
13
+ def initialize(x, y)
14
+ @x, @y = x.to_i, y.to_i
15
+ end
16
+
17
+ def to_s
18
+ "#{x} #{y}"
19
+ end
20
+
21
+ def >=(other)
22
+ x >= other.x && y >= other.y
23
+ end
24
+
25
+ def <=(other)
26
+ x <= other.x && y <= other.y
27
+ end
28
+
29
+ def ==(other)
30
+ x == other.x && y == other.y
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,24 @@
1
+ require "nasa_rovers/coord"
2
+
3
+ module NasaRovers
4
+ class Plateau
5
+ def self.factory(data, coord_class=Coord)
6
+ new(*data.split(" "), coord_class)
7
+ end
8
+
9
+ attr_reader :bot_lt, :top_rt
10
+
11
+ def initialize(x, y, coord_class=Coord)
12
+ @bot_lt = coord_class.origin
13
+ @top_rt = coord_class.new(x, y)
14
+ end
15
+
16
+ def include?(coord)
17
+ coord >= bot_lt && coord <= top_rt
18
+ end
19
+
20
+ def to_s
21
+ "#{bot_lt} - #{top_rt}"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,32 @@
1
+ require "nasa_rovers/coord"
2
+
3
+ module NasaRovers
4
+ class Position
5
+ class CardinalError < StandardError; end
6
+
7
+ def self.factory(data)
8
+ new(*data.split(" "))
9
+ end
10
+
11
+ attr_reader :coord
12
+ attr_accessor :cardinal
13
+
14
+ def initialize(x, y, cardinal, coord_class=Coord)
15
+ @coord = coord_class.new(x, y)
16
+ @cardinal = check(cardinal)
17
+ end
18
+
19
+ def to_s
20
+ "#{coord} #{cardinal}"
21
+ end
22
+
23
+ def ==(other)
24
+ coord == other.coord && cardinal == other.cardinal
25
+ end
26
+
27
+ private def check(cardinal)
28
+ return cardinal if CARDINALS.include?(cardinal)
29
+ fail CardinalError.new("#{cardinal} is not a valid cardinal point")
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,84 @@
1
+ require "forwardable"
2
+ require "nasa_rovers/plateau"
3
+ require "nasa_rovers/position"
4
+
5
+ module NasaRovers
6
+ class Rover
7
+ extend Forwardable
8
+
9
+ MAPPING = {
10
+ M: :move,
11
+ L: :left,
12
+ R: :right
13
+ }
14
+
15
+ INST_ROWS = 2
16
+
17
+ def self.factory(data, plateau, position_class=Position)
18
+ position = position_class.factory(data)
19
+ new(position, plateau)
20
+ end
21
+
22
+ def self.instruct(data, plateau_class=Plateau)
23
+ plateau = plateau_class.factory(data.shift)
24
+ data.each_slice(INST_ROWS).reduce([]) do |rovers, rows|
25
+ position, instructions = rows
26
+ rover = factory(position, plateau)
27
+ rover.call(instructions)
28
+ rovers << rover
29
+ end
30
+ end
31
+
32
+ def_delegators :@position, :cardinal, :coord, :to_s
33
+
34
+ attr_reader :plateau, :position
35
+
36
+ def initialize(position, plateau)
37
+ @position = position
38
+ @plateau = plateau
39
+ end
40
+
41
+ def call(data)
42
+ instructions(data).each do |inst|
43
+ action = MAPPING.fetch(inst) { :stay }
44
+ send(action)
45
+ end
46
+ end
47
+
48
+ private def instructions(data)
49
+ data.split("").map(&:strip).map(&:to_sym)
50
+ end
51
+
52
+ private def left
53
+ position.cardinal = CARDINALS[cardinal_idx-1]
54
+ end
55
+
56
+ private def right
57
+ idx = CARDINALS[cardinal_idx+1] ? cardinal_idx+1 : 0
58
+ position.cardinal = CARDINALS[idx]
59
+ end
60
+
61
+ private def cardinal_idx
62
+ CARDINALS.index(cardinal)
63
+ end
64
+
65
+ private def move
66
+ case cardinal
67
+ when "N"
68
+ coord.y += 1
69
+ coord.y = plateau.top_rt.y unless plateau.include?(coord)
70
+ when "E"
71
+ coord.x += 1
72
+ coord.x = plateau.top_rt.x unless plateau.include?(coord)
73
+ when "S"
74
+ coord.y -= 1
75
+ coord.y = plateau.bot_lt.y unless plateau.include?(coord)
76
+ when "W"
77
+ coord.x -= 1
78
+ coord.x = plateau.bot_lt.x unless plateau.include?(coord)
79
+ end
80
+ end
81
+
82
+ private def stay; end
83
+ end
84
+ end
@@ -0,0 +1,3 @@
1
+ module NasaRovers
2
+ VERSION = "1.0.1"
3
+ end
data/nasa_data.txt ADDED
@@ -0,0 +1,5 @@
1
+ 5 5
2
+ 1 2 N
3
+ LMLMLMLMM
4
+ 3 3 E
5
+ MMRMMRMRRM
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "nasa_rovers/version"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "nasa_rovers"
8
+ s.version = NasaRovers::VERSION
9
+ s.authors = ["costajob"]
10
+ s.email = ["costajob@gmail.com"]
11
+ s.summary = "The Ruby implementation of the NASA rovers code kata."
12
+ s.homepage = "https://github.com/costajob/nasa_rovers"
13
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
14
+ s.bindir = "bin"
15
+ s.executables << "nasa_rovers"
16
+ s.require_paths = ["lib"]
17
+ s.required_ruby_version = ">= 2.3.1"
18
+ s.add_development_dependency "bundler", "~> 1.16"
19
+ s.add_development_dependency "rake", "~> 12.3"
20
+ s.add_development_dependency "minitest", "~> 5.1"
21
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nasa_rovers
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - costajob
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-12-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '12.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '12.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.1'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.1'
55
+ description:
56
+ email:
57
+ - costajob@gmail.com
58
+ executables:
59
+ - nasa_rovers
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - ".ruby-version"
65
+ - ".travis.yml"
66
+ - Gemfile
67
+ - OBJECTIVES.md
68
+ - README.md
69
+ - Rakefile
70
+ - bin/console
71
+ - bin/nasa_rovers
72
+ - bin/setup
73
+ - lib/nasa_rovers.rb
74
+ - lib/nasa_rovers/cli.rb
75
+ - lib/nasa_rovers/coord.rb
76
+ - lib/nasa_rovers/plateau.rb
77
+ - lib/nasa_rovers/position.rb
78
+ - lib/nasa_rovers/rover.rb
79
+ - lib/nasa_rovers/version.rb
80
+ - nasa_data.txt
81
+ - nasa_rovers.gemspec
82
+ homepage: https://github.com/costajob/nasa_rovers
83
+ licenses: []
84
+ metadata: {}
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: 2.3.1
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 2.7.6
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: The Ruby implementation of the NASA rovers code kata.
105
+ test_files: []