simple-graph 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Build Status](https://secure.travis-ci.org/camertron/simple-graph.png?branch=master)](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: []
|