simple-graph 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,13 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development, :test do
6
+ gem 'pry-nav'
7
+ gem 'rake'
8
+ end
9
+
10
+ group :test do
11
+ gem 'rspec'
12
+ gem 'rr'
13
+ end
@@ -0,0 +1,3 @@
1
+ == 1.0.0
2
+
3
+ * Birthday!
@@ -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
@@ -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
@@ -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,5 @@
1
+ # encoding: UTF-8
2
+
3
+ module SimpleGraph
4
+ VERSION = "1.0.0"
5
+ 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
@@ -0,0 +1,11 @@
1
+ # encoding: UTF-8
2
+
3
+ $:.push(File.dirname(__FILE__))
4
+
5
+ require 'rspec'
6
+ require 'simple-graph'
7
+ require 'pry-nav'
8
+
9
+ RSpec.configure do |config|
10
+ config.mock_with :rr
11
+ end
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: []