djikstra 0.0.1
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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +62 -0
- data/Rakefile +7 -0
- data/bin/djikstra +7 -0
- data/djikstra.gemspec +24 -0
- data/lib/djikstra.rb +10 -0
- data/lib/djikstra/cli.rb +52 -0
- data/lib/djikstra/edge.rb +21 -0
- data/lib/djikstra/graph.rb +88 -0
- data/lib/djikstra/node.rb +42 -0
- data/lib/djikstra/version.rb +3 -0
- data/spec/bin/djikstra_spec.rb +55 -0
- data/spec/djikstra/cli_spec.rb +24 -0
- data/spec/djikstra/edge_spec.rb +55 -0
- data/spec/djikstra/graph_spec.rb +38 -0
- data/spec/djikstra/node_spec.rb +41 -0
- data/spec/files/bad.txt +2 -0
- data/spec/files/example.txt +10 -0
- data/spec/files/invalid.txt +3 -0
- data/spec/files/linear.txt +2 -0
- data/spec/files/simple.txt +1 -0
- data/spec/spec_helper.rb +18 -0
- metadata +125 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c8e3e25342dbb274d1b4670ff4a80c3cf04c70a8
|
4
|
+
data.tar.gz: 2a4917c41f3e2dfc54f30eaa0af1863d13c8f0fc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1e351f1acc0212724009b204a52da6678ad76c72347af45baadb894f1bc80290474eaee44cae1ed58eb6ad680ca6b78239927937ecd19fcce9b52508ea31bb58
|
7
|
+
data.tar.gz: 82790ff6a781b819a782f80c5e6af887abcc89c48e49f429c6c77b562841473d29292b4feea1b1ec62d64726f6b812569535266a6d10f937c568e40840ac0a4a
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.1.0
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 John Kamenik
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# Djikstra
|
2
|
+
|
3
|
+
[](https://travis-ci.org/jkamenik/djikstra)
|
4
|
+
|
5
|
+
Djikstra's algorithm is a graph-based technique for finding the globally shortest path between a starting node and a target node in a non-negative weighted Directed Acyclic Graph (DAG). It is a DAG in that edges are one way and there are no cycles in the graph; it is weighted in that each traversal of the graph has a certain cost. It is used often in graph-based applications such as social, network routing, and logistics supply modeling.
|
6
|
+
In its simplest form, the algorithm performs in O(v2) where |v| is the number of vertices in the graph.
|
7
|
+
|
8
|
+
Details of the algorithm may be found here:
|
9
|
+
|
10
|
+
* [Wikipedia](http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)
|
11
|
+
* [YouTube](http://www.youtube.com/watch?v=gdmfOwyQlcI)
|
12
|
+
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add this line to your application's Gemfile:
|
17
|
+
|
18
|
+
gem 'djikstra'
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
$ gem install djikstra
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
Use the `djikstra` command and pass it a graph file, a starting node, and an ending node.
|
31
|
+
|
32
|
+
$ djikstra my_graph.txt A G
|
33
|
+
Shortest path is [A,B,E,G] with total cost 6
|
34
|
+
|
35
|
+
### graph file
|
36
|
+
|
37
|
+
A graph file is a txt file containing lines and weights. A line consists of two nodes.
|
38
|
+
|
39
|
+
[A,B,1]
|
40
|
+
[B,C,3]
|
41
|
+
[C,D,1]
|
42
|
+
[D,F,3]
|
43
|
+
[E,G,3]
|
44
|
+
[F,G,1]
|
45
|
+
[A,C,2]
|
46
|
+
[B,D,3]
|
47
|
+
[B,E,2]
|
48
|
+
[D,E,3]
|
49
|
+
|
50
|
+
This file must be a Direct Acyclic Graph (DAG):
|
51
|
+
|
52
|
+
1. Lines are one way
|
53
|
+
1. Lines are always weighted
|
54
|
+
1. There are no cycles
|
55
|
+
|
56
|
+
## Contributing
|
57
|
+
|
58
|
+
1. Fork it ( http://github.com/jkamenik/djikstra/fork )
|
59
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
60
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
61
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
62
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/djikstra
ADDED
data/djikstra.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'djikstra/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "djikstra"
|
8
|
+
spec.version = Djikstra::VERSION
|
9
|
+
spec.authors = ["John Kamenik"]
|
10
|
+
spec.email = ["jkamenik@gmail.com"]
|
11
|
+
spec.summary = %Q{djikstra-#{Djikstra::VERSION}}
|
12
|
+
spec.description = %q{Runs the Djikstra algorithm against a graph file.}
|
13
|
+
spec.homepage = "http://github.com/jkamenik/djikstra"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
end
|
data/lib/djikstra.rb
ADDED
data/lib/djikstra/cli.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Djikstra
|
2
|
+
class Cli
|
3
|
+
def initialize(*args)
|
4
|
+
@file = args[0]
|
5
|
+
@start = args[1].to_s.upcase
|
6
|
+
@stop = args[2].to_s.upcase
|
7
|
+
end
|
8
|
+
|
9
|
+
def usage
|
10
|
+
puts "#{$0} <file> <start> <end>"
|
11
|
+
puts " file - a DAG graph file"
|
12
|
+
puts " start - the name of starting node"
|
13
|
+
puts " end - the name of the ending node"
|
14
|
+
puts
|
15
|
+
puts " DAG graph file contains lines (between two nodes) and weights in the following format"
|
16
|
+
puts " [A,B,1]"
|
17
|
+
puts " [B,C,3]"
|
18
|
+
puts
|
19
|
+
puts "Example:"
|
20
|
+
puts " $ #{$0} graph.txt A C"
|
21
|
+
puts " Shortest path is [A,B,C] with total cost 4"
|
22
|
+
|
23
|
+
exit 1
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse
|
27
|
+
edges = []
|
28
|
+
open(@file) do |f|
|
29
|
+
f.readlines.each_with_index do |line,idx|
|
30
|
+
items = line.split /\[(\w+),(\w+),(\d+)\]/
|
31
|
+
|
32
|
+
# only care about the center matches
|
33
|
+
edges.push [items[1],items[2],items[3],idx+1]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
edges
|
37
|
+
end
|
38
|
+
|
39
|
+
def run
|
40
|
+
return usage unless @file && @start && @stop
|
41
|
+
|
42
|
+
graph = Graph.new(parse)
|
43
|
+
path = graph.shortest_path_between(@start,@stop)
|
44
|
+
dist = graph.shortest_path_distance
|
45
|
+
|
46
|
+
puts "Shortest path is [#{path.join(',')}] with a total cost of #{dist}"
|
47
|
+
rescue ParseError, GraphError => e
|
48
|
+
puts e.to_s
|
49
|
+
exit 1
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Djikstra
|
2
|
+
class Edge
|
3
|
+
attr_accessor :graph, :start, :stop, :weight
|
4
|
+
|
5
|
+
def initialize(graph,start,stop,weight,line=0)
|
6
|
+
raise ParseError, "Invalid edge on line #{line}" unless start && stop && weight
|
7
|
+
|
8
|
+
@graph = graph
|
9
|
+
@start = graph.find_node(start.to_s.upcase)
|
10
|
+
@stop = graph.find_node(stop.to_s.upcase)
|
11
|
+
@weight = Integer(weight)
|
12
|
+
|
13
|
+
@start.neighbor_of(@stop, @weight)
|
14
|
+
@stop.neighbor_of(@start, @weight)
|
15
|
+
rescue TypeError, ArgumentError
|
16
|
+
# Integer may raise this, so reraise as a ParseError
|
17
|
+
raise ParseError, "Invalid weight on line #{line}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Djikstra
|
2
|
+
class Graph
|
3
|
+
attr_reader :nodes, :edges, :shortest_path_distance
|
4
|
+
|
5
|
+
def initialize(edges=[])
|
6
|
+
@nodes = {}
|
7
|
+
@edges = []
|
8
|
+
|
9
|
+
edges.each do |e|
|
10
|
+
args = e.unshift self
|
11
|
+
|
12
|
+
@edges.push Edge.new(*args)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_node(name,raise_if_note_found=false)
|
17
|
+
node = @nodes[name]
|
18
|
+
return node if node
|
19
|
+
|
20
|
+
raise GraphError, %Q(Node "#{name}" not found!) if raise_if_note_found
|
21
|
+
|
22
|
+
node = Node.new name
|
23
|
+
@nodes[name] = node
|
24
|
+
node
|
25
|
+
end
|
26
|
+
|
27
|
+
def shortest_path_between(start,stop)
|
28
|
+
universe = []
|
29
|
+
|
30
|
+
@nodes.each do |key,node|
|
31
|
+
node.reset
|
32
|
+
|
33
|
+
universe.push node
|
34
|
+
end
|
35
|
+
|
36
|
+
start_node = find_node(start, true)
|
37
|
+
start_node.distance = 0
|
38
|
+
|
39
|
+
while universe.size > 0
|
40
|
+
start_node.neighbors.each do |neighbor|
|
41
|
+
next unless universe.include? neighbor #skip visited nodes
|
42
|
+
|
43
|
+
# untraversable branch
|
44
|
+
raise GraphError, %Q(Node "#{start_node.name}" is not reachable) if start_node.infinite?
|
45
|
+
|
46
|
+
dist = start_node.distance + start_node.distance_to(neighbor)
|
47
|
+
|
48
|
+
if neighbor > dist
|
49
|
+
neighbor.distance = dist
|
50
|
+
neighbor.previous_node = start_node # collect the shortest path back
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
universe.delete start_node
|
55
|
+
|
56
|
+
start_node = closest(universe)
|
57
|
+
end
|
58
|
+
|
59
|
+
# walk backwards
|
60
|
+
start_node = find_node(start, true)
|
61
|
+
stop_node = find_node(stop, true)
|
62
|
+
collect_shortest_path_between(start_node,stop_node)
|
63
|
+
end
|
64
|
+
|
65
|
+
def collect_shortest_path_between(start_node,end_node)
|
66
|
+
# artifact, the distance is the end_node distance
|
67
|
+
@shortest_path_distance = end_node.distance
|
68
|
+
|
69
|
+
# walk from the end node down the previous_node list
|
70
|
+
node = end_node
|
71
|
+
path = [node.name]
|
72
|
+
while node && node != start_node
|
73
|
+
node = node.previous_node
|
74
|
+
path.insert 0, node.name
|
75
|
+
end
|
76
|
+
path
|
77
|
+
end
|
78
|
+
|
79
|
+
def closest(universe)
|
80
|
+
u = universe.first
|
81
|
+
|
82
|
+
universe.each do |node|
|
83
|
+
u = node if u > node.distance
|
84
|
+
end
|
85
|
+
u
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Djikstra
|
2
|
+
class Node
|
3
|
+
attr_accessor :name, :distance, :neighbors, :previous_node
|
4
|
+
|
5
|
+
def initialize(name)
|
6
|
+
@name = name
|
7
|
+
@neighbors = []
|
8
|
+
@weights = {}
|
9
|
+
reset
|
10
|
+
end
|
11
|
+
|
12
|
+
def reset
|
13
|
+
@distance = :infinity
|
14
|
+
@previous_node = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def neighbor_of(node, weight)
|
18
|
+
@neighbors.push node
|
19
|
+
@weights[node.name] = weight
|
20
|
+
end
|
21
|
+
|
22
|
+
def distance_to(node)
|
23
|
+
@weights[node.name]
|
24
|
+
end
|
25
|
+
|
26
|
+
def infinite?
|
27
|
+
@distance == :infinity
|
28
|
+
end
|
29
|
+
|
30
|
+
def >(number)
|
31
|
+
return true if infinite?
|
32
|
+
return false if number == :infinity
|
33
|
+
|
34
|
+
distance > number
|
35
|
+
end
|
36
|
+
|
37
|
+
def inspect
|
38
|
+
%Q(#<Djikstra::Node name="#{name}" distance=#{distance}>)
|
39
|
+
end
|
40
|
+
alias_method :to_s, :inspect
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Output
|
4
|
+
attr_reader :output, :exitcode
|
5
|
+
|
6
|
+
def initialize(output,exitcode)
|
7
|
+
@output = output
|
8
|
+
@exitcode = exitcode
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
@output
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_i
|
16
|
+
@exitcode
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
describe 'CLI' do
|
22
|
+
def djikstra(*args)
|
23
|
+
command = File.expand_path("../../../bin/djikstra",__FILE__)
|
24
|
+
args[0] = File.expand_path("../../files/#{args[0]}",__FILE__) if args[0]
|
25
|
+
output = `ruby #{command} #{args.join ' '}`
|
26
|
+
|
27
|
+
Output.new output.chop, $?.exitstatus
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'requires three arguments' do
|
31
|
+
expect(djikstra.exitcode).to eq 1
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'states the shortest path' do
|
35
|
+
expect(djikstra('example.txt','A','G').output).to eq 'Shortest path is [A,B,E,G] with a total cost of 6'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'works for the simple case' do
|
39
|
+
expect(djikstra('simple.txt','A','B').output).to eq 'Shortest path is [A,B] with a total cost of 1'
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'works for a linear case' do
|
43
|
+
expect(djikstra('linear.txt','A','C').output).to eq 'Shortest path is [A,B,C] with a total cost of 2'
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'shows an error if the end node doesn\'t exist' do
|
47
|
+
# "E" doesn't exist as a node.
|
48
|
+
expect(djikstra('linear.txt','A','E').output).to eq 'Node "E" not found!'
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'shows an error if the end node doesn\'t exist' do
|
52
|
+
# "E" doesn't exist as a node.
|
53
|
+
expect(djikstra('linear.txt','E','C').output).to eq 'Node "E" not found!'
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Djikstra::Cli do
|
4
|
+
def spec_file(file)
|
5
|
+
File.expand_path("../../files/#{file}",__FILE__)
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'prints usage if args is less then 3' do
|
9
|
+
cli = Djikstra::Cli.new()
|
10
|
+
|
11
|
+
expect(cli).to receive :usage
|
12
|
+
|
13
|
+
cli.run
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'parse' do
|
17
|
+
it 'returns an array of weighted edges' do
|
18
|
+
items = Djikstra::Cli.new(spec_file('simple.txt'),'A','B').parse
|
19
|
+
|
20
|
+
expect(items).to be_an Array
|
21
|
+
expect(items[0]).to eq ['A','B','1',1]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Djikstra::Edge do
|
4
|
+
let(:graph) { Djikstra::Graph.new }
|
5
|
+
|
6
|
+
it 'errors if start is not provided' do
|
7
|
+
expect {
|
8
|
+
Djikstra::Edge.new(graph,nil,'B',1)
|
9
|
+
}.to raise_error Djikstra::ParseError
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'errors if stop is not provided' do
|
13
|
+
expect {
|
14
|
+
Djikstra::Edge.new(graph,'A',nil,1)
|
15
|
+
}.to raise_error Djikstra::ParseError
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'errors if weight is not provided' do
|
19
|
+
expect {
|
20
|
+
Djikstra::Edge.new(graph,'A','B',nil)
|
21
|
+
}.to raise_error Djikstra::ParseError
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'errors if weight is not an integer' do
|
25
|
+
expect {
|
26
|
+
Djikstra::Edge.new(graph,'A','B','G')
|
27
|
+
}.to raise_error Djikstra::ParseError
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'start' do
|
31
|
+
it 'is a Node' do
|
32
|
+
edge = Djikstra::Edge.new(graph,'A','B',1)
|
33
|
+
expect(edge.start).to be_a Djikstra::Node
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'has stop as a neighbor' do
|
37
|
+
edge = Djikstra::Edge.new(graph,'A','B',1)
|
38
|
+
|
39
|
+
expect(edge.start.neighbors).to include edge.stop
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'stop' do
|
44
|
+
it 'is a Node' do
|
45
|
+
edge = Djikstra::Edge.new(graph,'A','B',1)
|
46
|
+
expect(edge.stop).to be_a Djikstra::Node
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'has start as a neighbor' do
|
50
|
+
edge = Djikstra::Edge.new(graph,'A','B',1)
|
51
|
+
|
52
|
+
expect(edge.stop.neighbors).to include edge.start
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Djikstra::Graph do
|
4
|
+
context '.new' do
|
5
|
+
it 'takes edge tupples and creates edges' do
|
6
|
+
graph = Djikstra::Graph.new [['A','B','1',1]]
|
7
|
+
|
8
|
+
expect(graph.edges).to be_an Array
|
9
|
+
expect(graph.edges[0]).to be_a Djikstra::Edge
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context '.find_node' do
|
14
|
+
it 'returns the found node' do
|
15
|
+
graph = Djikstra::Graph.new
|
16
|
+
node1 = graph.find_node('strange')
|
17
|
+
node2 = graph.find_node('strange')
|
18
|
+
|
19
|
+
expect(node1.object_id).to eq node2.object_id
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'creates a new node if one does not exist' do
|
23
|
+
graph = Djikstra::Graph.new
|
24
|
+
node = graph.find_node('strange')
|
25
|
+
|
26
|
+
expect(node).to be_a Djikstra::Node
|
27
|
+
expect(node.name).to eq 'strange'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context '.shortest_path_between' do
|
32
|
+
it 'returns that path' do
|
33
|
+
graph = Djikstra::Graph.new [['A','B','1',1]]
|
34
|
+
|
35
|
+
expect(graph.shortest_path_between('A','B')).to eq ['A','B']
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Djikstra::Node do
|
4
|
+
let(:node) { Djikstra::Node.new 'A' }
|
5
|
+
|
6
|
+
context '.reset' do
|
7
|
+
it 'resets distance to infinity' do
|
8
|
+
node.distance = 1
|
9
|
+
|
10
|
+
node.reset
|
11
|
+
expect(node.distance).to eq :infinity
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'removes any previous nodes' do
|
15
|
+
node.previous_node = node
|
16
|
+
|
17
|
+
node.reset
|
18
|
+
expect(node.reset).to eq nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context ">" do
|
23
|
+
it 'returns true if my distance is infinity' do
|
24
|
+
node.distance = :infinity
|
25
|
+
|
26
|
+
expect(node > 1_000_000_000_000).to be_true
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns false if the number is infinity' do
|
30
|
+
node.distance = 1_000_000_000_000
|
31
|
+
|
32
|
+
expect(node > :infinity).to be_false
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'compares distance to number' do
|
36
|
+
node.distance = 1
|
37
|
+
|
38
|
+
expect(node > 2).to be_false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/spec/files/bad.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
[A,B,1]
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'djikstra'
|
2
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
3
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
4
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
5
|
+
# loaded once.
|
6
|
+
#
|
7
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
10
|
+
config.run_all_when_everything_filtered = true
|
11
|
+
config.filter_run :focus
|
12
|
+
|
13
|
+
# Run specs in random order to surface order dependencies. If you find an
|
14
|
+
# order dependency and want to debug it, you can fix the order by providing
|
15
|
+
# the seed, which is printed after each run.
|
16
|
+
# --seed 1234
|
17
|
+
config.order = 'random'
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: djikstra
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- John Kamenik
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-27 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.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Runs the Djikstra algorithm against a graph file.
|
56
|
+
email:
|
57
|
+
- jkamenik@gmail.com
|
58
|
+
executables:
|
59
|
+
- djikstra
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".gitignore"
|
64
|
+
- ".rspec"
|
65
|
+
- ".ruby-version"
|
66
|
+
- ".travis.yml"
|
67
|
+
- Gemfile
|
68
|
+
- LICENSE.txt
|
69
|
+
- README.md
|
70
|
+
- Rakefile
|
71
|
+
- bin/djikstra
|
72
|
+
- djikstra.gemspec
|
73
|
+
- lib/djikstra.rb
|
74
|
+
- lib/djikstra/cli.rb
|
75
|
+
- lib/djikstra/edge.rb
|
76
|
+
- lib/djikstra/graph.rb
|
77
|
+
- lib/djikstra/node.rb
|
78
|
+
- lib/djikstra/version.rb
|
79
|
+
- spec/bin/djikstra_spec.rb
|
80
|
+
- spec/djikstra/cli_spec.rb
|
81
|
+
- spec/djikstra/edge_spec.rb
|
82
|
+
- spec/djikstra/graph_spec.rb
|
83
|
+
- spec/djikstra/node_spec.rb
|
84
|
+
- spec/files/bad.txt
|
85
|
+
- spec/files/example.txt
|
86
|
+
- spec/files/invalid.txt
|
87
|
+
- spec/files/linear.txt
|
88
|
+
- spec/files/simple.txt
|
89
|
+
- spec/spec_helper.rb
|
90
|
+
homepage: http://github.com/jkamenik/djikstra
|
91
|
+
licenses:
|
92
|
+
- MIT
|
93
|
+
metadata: {}
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 2.2.2
|
111
|
+
signing_key:
|
112
|
+
specification_version: 4
|
113
|
+
summary: djikstra-0.0.1
|
114
|
+
test_files:
|
115
|
+
- spec/bin/djikstra_spec.rb
|
116
|
+
- spec/djikstra/cli_spec.rb
|
117
|
+
- spec/djikstra/edge_spec.rb
|
118
|
+
- spec/djikstra/graph_spec.rb
|
119
|
+
- spec/djikstra/node_spec.rb
|
120
|
+
- spec/files/bad.txt
|
121
|
+
- spec/files/example.txt
|
122
|
+
- spec/files/invalid.txt
|
123
|
+
- spec/files/linear.txt
|
124
|
+
- spec/files/simple.txt
|
125
|
+
- spec/spec_helper.rb
|