simple-graph 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.
- checksums.yaml +7 -0
- data/Gemfile +13 -0
- data/History.txt +3 -0
- data/README.md +57 -0
- data/Rakefile +18 -0
- data/lib/simple-graph.rb +90 -0
- data/lib/simple-graph/version.rb +5 -0
- data/simple-graph.gemspec +18 -0
- data/spec/simple-graph_spec.rb +50 -0
- data/spec/spec_helper.rb +11 -0
- metadata +52 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9df289cf2e820574d29a3423187552d0f41cd4be
|
4
|
+
data.tar.gz: 28ff78a5bc850c98b9507a13f32ee7dfb548267e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5f87b5205d846ab77fcd96a0b004bc602088affae6ebc23be3e8eccae760e077e92402ed7fea1060f5834071748ace4335f2c469f3cd91caaedd7cc922808438
|
7
|
+
data.tar.gz: c0ab5acf01b7d4c436e3f3b477db72c702984294770373de8ebf77923cfe5a1c6ea86e5c8c628bf22004c2a31114b8e5d1b3ceb36d7f3b66c072f56e2b1be8d0
|
data/Gemfile
ADDED
data/History.txt
ADDED
data/README.md
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
|
2
|
+
## simple-graph [](http://travis-ci.org/camertron/simple-graph)
|
3
|
+
|
4
|
+
A simple, no-frills graph implementation.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
`gem install simple-graph`
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
require 'simple-graph'
|
14
|
+
```
|
15
|
+
|
16
|
+
### Adding Vertices
|
17
|
+
|
18
|
+
Let's model an airline that flies to certain cities:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
graph = SimpleGraph::Graph.new
|
22
|
+
graph.add_vertex('Seattle')
|
23
|
+
graph.add_vertex('Los Angeles')
|
24
|
+
graph.add_vertex('Denver')
|
25
|
+
graph.add_vertex('New York')
|
26
|
+
graph.add_vertex('Miami')
|
27
|
+
```
|
28
|
+
|
29
|
+
### Adding Edges
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
graph.add_edge('Seattle', 'Los Angeles')
|
33
|
+
graph.add_edge('Seattle', 'Denver')
|
34
|
+
graph.add_edge('Los Angeles', 'Miami')
|
35
|
+
graph.add_edge('Denver', 'New York')
|
36
|
+
graph.add_edge('New York', 'Miami')
|
37
|
+
```
|
38
|
+
|
39
|
+
### Shortest Path
|
40
|
+
|
41
|
+
SimpleGraph doesn't support weighted edges, so let's pretend all these cities are equidistant from each other. We could also say we're trying to find the least number of layovers:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
graph.shortest_path('Seattle', 'Miami') # ["Seattle", "Los Angeles", "Miami"]
|
45
|
+
```
|
46
|
+
|
47
|
+
## Requirements
|
48
|
+
|
49
|
+
None.
|
50
|
+
|
51
|
+
## Running Tests
|
52
|
+
|
53
|
+
`bundle exec rspec`
|
54
|
+
|
55
|
+
## Authors
|
56
|
+
|
57
|
+
* Cameron C. Dutro: http://github.com/camertron
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
4
|
+
|
5
|
+
require 'bundler'
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
require 'rubygems/package_task'
|
8
|
+
|
9
|
+
require './lib/simple-graph'
|
10
|
+
|
11
|
+
Bundler::GemHelper.install_tasks
|
12
|
+
|
13
|
+
task :default => :spec
|
14
|
+
|
15
|
+
desc 'Run specs'
|
16
|
+
RSpec::Core::RakeTask.new do |t|
|
17
|
+
t.pattern = './spec/**/*_spec.rb'
|
18
|
+
end
|
data/lib/simple-graph.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module SimpleGraph
|
4
|
+
|
5
|
+
class Vertex
|
6
|
+
attr_reader :value, :neighbors
|
7
|
+
|
8
|
+
def initialize(value, neighbors = {})
|
9
|
+
@value = value
|
10
|
+
@neighbors = neighbors || {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_neighbor(vertex)
|
14
|
+
neighbors[vertex.value] ||= vertex
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Graph
|
19
|
+
attr_reader :vertices
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@vertices = {}
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_vertex(value)
|
26
|
+
vertices[value] ||= create_vertex(value)
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_edge(value1, value2)
|
30
|
+
vertices[value1].add_neighbor(vertices[value2])
|
31
|
+
end
|
32
|
+
|
33
|
+
# Djikstra's shortest path algorithm, adapted from:
|
34
|
+
# https://gist.github.com/yaraki/1730288
|
35
|
+
def shortest_path(source, target = nil)
|
36
|
+
distances = {}
|
37
|
+
previouses = {}
|
38
|
+
|
39
|
+
vertices.each_pair do |key, vertex|
|
40
|
+
distances[key] = nil # Infinity
|
41
|
+
previouses[key] = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
distances[source] = 0
|
45
|
+
verts = vertices.clone
|
46
|
+
|
47
|
+
until verts.empty?
|
48
|
+
nearest_vertex = verts.inject(verts.first.first) do |a, (b, c)|
|
49
|
+
next b unless distances[a]
|
50
|
+
next a unless distances[b]
|
51
|
+
next a if distances[a] < distances[b]
|
52
|
+
b
|
53
|
+
end
|
54
|
+
|
55
|
+
break unless distances[nearest_vertex] # Infinity
|
56
|
+
|
57
|
+
if target && nearest_vertex == target
|
58
|
+
return compose_path(target, distances[target], previouses)
|
59
|
+
end
|
60
|
+
|
61
|
+
neighbors = verts[nearest_vertex].neighbors
|
62
|
+
neighbors.each_pair do |name, vertex|
|
63
|
+
alt = distances[nearest_vertex] + 1
|
64
|
+
|
65
|
+
if distances[name].nil? || alt < distances[name]
|
66
|
+
distances[name] = alt
|
67
|
+
previouses[name] = nearest_vertex
|
68
|
+
end
|
69
|
+
end
|
70
|
+
verts.delete(nearest_vertex)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def compose_path(target, distance, previouses)
|
77
|
+
result = Array.new(distance)
|
78
|
+
distance.downto(0) do |i|
|
79
|
+
result[i] = target
|
80
|
+
target = previouses[target]
|
81
|
+
end
|
82
|
+
result
|
83
|
+
end
|
84
|
+
|
85
|
+
def create_vertex(value, edges = nil)
|
86
|
+
Vertex.new(value, edges)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
2
|
+
require 'simple-graph/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "simple-graph"
|
6
|
+
s.version = ::SimpleGraph::VERSION
|
7
|
+
s.authors = ["Cameron Dutro"]
|
8
|
+
s.email = ["camertron@gmail.com"]
|
9
|
+
s.homepage = "http://github.com/camertron"
|
10
|
+
|
11
|
+
s.description = s.summary = "A simple, no-frills graph implementation."
|
12
|
+
|
13
|
+
s.platform = Gem::Platform::RUBY
|
14
|
+
s.has_rdoc = true
|
15
|
+
|
16
|
+
s.require_path = 'lib'
|
17
|
+
s.files = Dir["{lib,spec}/**/*", "Gemfile", "History.txt", "README.md", "Rakefile", "simple-graph.gemspec"]
|
18
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe SimpleGraph do
|
6
|
+
let(:graph) { SimpleGraph::Graph.new }
|
7
|
+
|
8
|
+
describe '#add_vertex' do
|
9
|
+
it 'should add vertices correctly' do
|
10
|
+
graph.add_vertex('Seattle').tap do |vertex|
|
11
|
+
expect(vertex).to be_a(SimpleGraph::Vertex)
|
12
|
+
expect(vertex.value).to eq('Seattle')
|
13
|
+
expect(vertex.neighbors).to eq({})
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#add_edge' do
|
19
|
+
it 'should add edges correctly' do
|
20
|
+
seattle = graph.add_vertex('Seattle')
|
21
|
+
la = graph.add_vertex('Los Angeles')
|
22
|
+
graph.add_edge('Seattle', 'Los Angeles')
|
23
|
+
expect(seattle.neighbors).to include('Los Angeles')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'with a nice graph' do
|
28
|
+
before(:each) do
|
29
|
+
graph.add_vertex('Seattle')
|
30
|
+
graph.add_vertex('Los Angeles')
|
31
|
+
graph.add_vertex('Denver')
|
32
|
+
graph.add_vertex('New York')
|
33
|
+
graph.add_vertex('Miami')
|
34
|
+
|
35
|
+
graph.add_edge('Seattle', 'Los Angeles')
|
36
|
+
graph.add_edge('Seattle', 'Denver')
|
37
|
+
graph.add_edge('Los Angeles', 'Miami')
|
38
|
+
graph.add_edge('Denver', 'New York')
|
39
|
+
graph.add_edge('New York', 'Miami')
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#shortest_path' do
|
43
|
+
it 'finds the shortest path' do
|
44
|
+
expect(graph.shortest_path('Seattle', 'Miami')).to eq([
|
45
|
+
"Seattle", "Los Angeles", "Miami"
|
46
|
+
])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple-graph
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cameron Dutro
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-23 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A simple, no-frills graph implementation.
|
14
|
+
email:
|
15
|
+
- camertron@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- Gemfile
|
21
|
+
- History.txt
|
22
|
+
- README.md
|
23
|
+
- Rakefile
|
24
|
+
- lib/simple-graph.rb
|
25
|
+
- lib/simple-graph/version.rb
|
26
|
+
- simple-graph.gemspec
|
27
|
+
- spec/simple-graph_spec.rb
|
28
|
+
- spec/spec_helper.rb
|
29
|
+
homepage: http://github.com/camertron
|
30
|
+
licenses: []
|
31
|
+
metadata: {}
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
requirements: []
|
47
|
+
rubyforge_project:
|
48
|
+
rubygems_version: 2.2.2
|
49
|
+
signing_key:
|
50
|
+
specification_version: 4
|
51
|
+
summary: A simple, no-frills graph implementation.
|
52
|
+
test_files: []
|