topological_sort 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,11 @@
1
+ # .document is used by rdoc and yard to know how to generate documentation
2
+ # for example, it can be used to control how rdoc gets built when you do `gem install foo`
3
+
4
+ README.rdoc
5
+ lib/**/*.rb
6
+ bin/*
7
+
8
+ # Files below this - are treated as 'extra files', and aren't parsed for ruby code
9
+ -
10
+ features/**/*.feature
11
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,42 @@
1
+ # rcov generated
2
+ coverage
3
+
4
+ # rdoc generated
5
+ rdoc
6
+
7
+ # yard generated
8
+ doc
9
+ .yardoc
10
+
11
+ # bundler
12
+ .bundle
13
+
14
+ # jeweler generated
15
+ pkg
16
+
17
+ # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
18
+ #
19
+ # * Create a file at ~/.gitignore
20
+ # * Include files you want ignored
21
+ # * Run: git config --global core.excludesfile ~/.gitignore
22
+ #
23
+ # After doing this, these files will be ignored in all your git projects,
24
+ # saving you from having to 'pollute' every project you touch with them
25
+ #
26
+ # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
27
+ #
28
+ # For MacOS:
29
+ #
30
+ #.DS_Store
31
+ #
32
+ # For TextMate
33
+ #*.tmproj
34
+ #tmtags
35
+ #
36
+ # For emacs:
37
+ #*~
38
+ #\#*
39
+ #.\#*
40
+ #
41
+ # For vim:
42
+ #*.swp
data/.project ADDED
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <projectDescription>
3
+ <name>topological_sort</name>
4
+ <comment></comment>
5
+ <projects>
6
+ </projects>
7
+ <buildSpec>
8
+ </buildSpec>
9
+ <natures>
10
+ <nature>org.radrails.rails.core.railsnature</nature>
11
+ </natures>
12
+ </projectDescription>
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rspec", ">= 2.0.0.beta.19"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.5.0.pre3"
12
+ gem "rcov", ">= 0"
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,30 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ git (1.2.5)
6
+ jeweler (1.5.0.pre3)
7
+ bundler (~> 1.0.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ rake (0.8.7)
11
+ rcov (0.9.9)
12
+ rspec (2.0.0.rc)
13
+ rspec-core (= 2.0.0.rc)
14
+ rspec-expectations (= 2.0.0.rc)
15
+ rspec-mocks (= 2.0.0.rc)
16
+ rspec-core (2.0.0.rc)
17
+ rspec-expectations (2.0.0.rc)
18
+ diff-lcs (>= 1.1.2)
19
+ rspec-mocks (2.0.0.rc)
20
+ rspec-core (= 2.0.0.rc)
21
+ rspec-expectations (= 2.0.0.rc)
22
+
23
+ PLATFORMS
24
+ ruby
25
+
26
+ DEPENDENCIES
27
+ bundler (~> 1.0.0)
28
+ jeweler (~> 1.5.0.pre3)
29
+ rcov
30
+ rspec (>= 2.0.0.beta.19)
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Victor Costan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,17 @@
1
+ = new
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Victor Costan. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "topological_sort"
16
+ gem.summary = %Q{Topological sorting in arbitrary directed graphs.}
17
+ gem.description = %Q{Generic implementation of DFS for topological sorting.}
18
+ gem.email = "victor@costan.us"
19
+ gem.homepage = "http://github.com/pwnall/new"
20
+ gem.authors = ["Victor Costan"]
21
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
22
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
23
+ # spec.add_runtime_dependency 'jabber4r', '> 0.1'
24
+ # spec.add_development_dependency 'rspec', '> 1.2.3'
25
+ gem.add_development_dependency "rspec", ">= 2.0.0.beta.19"
26
+ gem.add_development_dependency "bundler", "~> 1.0.0"
27
+ gem.add_development_dependency "jeweler", "~> 1.5.0.pre3"
28
+ gem.add_development_dependency "rcov", ">= 0"
29
+ end
30
+ Jeweler::RubygemsDotOrgTasks.new
31
+
32
+ require 'rspec/core'
33
+ require 'rspec/core/rake_task'
34
+ RSpec::Core::RakeTask.new(:spec) do |spec|
35
+ spec.pattern = FileList['spec/**/*_spec.rb']
36
+ end
37
+
38
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
39
+ spec.pattern = 'spec/**/*_spec.rb'
40
+ spec.rcov = true
41
+ end
42
+
43
+ task :default => :spec
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "new #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,62 @@
1
+ require 'set'
2
+
3
+ # Performs a topological sort on a graph.
4
+ #
5
+ # Args:
6
+ # nodes:: Enumerable of all the nodes in the graph, or at least a subset of
7
+ # nodes that the entire graph is reachable from
8
+ #
9
+ # Requires a block that takes a node as an argument and returns a hash with the
10
+ # following keys:
11
+ # :id:: a unique ID for the node; this makes the algorithm work with graphs
12
+ # that have multiple objects representing the same node; if the :id key
13
+ # is not set, the node object is used as its own ID
14
+ # :next:: array of nodes that are reachable by direct edges from the given
15
+ # node; if the :next key is not set, the given node is assumed to be a
16
+ # sink
17
+ #
18
+ # Returns the graph's nodes, in topological order. This means that if node A is
19
+ # before node B, there is no path from A to B in the graph.
20
+ #
21
+ # Raises an ArgumentError if the graph is cyclic.
22
+ def topological_sort(root_nodes)
23
+ nodes = []
24
+
25
+ # Topological-sorting DFS.
26
+ visited = Set.new # IDs for the visited nodes.
27
+ active = Set.new # IDs for the nodes that are currently on the stack.
28
+ stack = [] # DFS stack state. Entries are [node, id, child_number, children].
29
+ root_nodes.each do |root_node|
30
+ node_data = yield root_node
31
+ node_id = node_data.has_key?(:id) ? node_data[:id] : root_node
32
+ next if visited.include? node_id
33
+
34
+ visited << node_id
35
+ stack << [root_node, node_id, -1, node_data[:next] || []]
36
+ active << node_id
37
+
38
+ until stack.empty?
39
+ stack.last[2] += 1
40
+ node, node_id, child_number, children = *stack.last
41
+
42
+ if child_node = children[child_number]
43
+ node_data = yield child_node
44
+ node_id = node_data.has_key?(:id) ? node_data[:id] : child_node
45
+ if active.include? node_id
46
+ raise ArgumentError, 'Cyclical graph'
47
+ end
48
+ unless visited.include? node_id
49
+ visited << node_id
50
+ active << node_id
51
+ stack << [child_node, node_id, -1, node_data[:next] || []]
52
+ end
53
+ else
54
+ nodes << node
55
+ active.delete stack.last[1]
56
+ stack.pop
57
+ end
58
+ end
59
+ end
60
+
61
+ nodes
62
+ end
data/new.gemspec ADDED
@@ -0,0 +1,77 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{new}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Victor Costan"]
12
+ s.date = %q{2010-10-08}
13
+ s.description = %q{Generic implementation of DFS for topological sorting.}
14
+ s.email = %q{victor@costan.us}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ ".project",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "lib/topological_sort.rb",
30
+ "spec/.rspec",
31
+ "spec/spec_helper.rb",
32
+ "spec/topological_sort_spec.rb"
33
+ ]
34
+ s.homepage = %q{http://github.com/pwnall/new}
35
+ s.require_paths = ["lib"]
36
+ s.rubygems_version = %q{1.3.7}
37
+ s.summary = %q{Topological sorting in arbitrary directed graphs.}
38
+ s.test_files = [
39
+ "spec/spec_helper.rb",
40
+ "spec/topological_sort_spec.rb"
41
+ ]
42
+
43
+ if s.respond_to? :specification_version then
44
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
45
+ s.specification_version = 3
46
+
47
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
48
+ s.add_development_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
49
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
50
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
51
+ s.add_development_dependency(%q<rcov>, [">= 0"])
52
+ s.add_development_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
53
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
54
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
55
+ s.add_development_dependency(%q<rcov>, [">= 0"])
56
+ else
57
+ s.add_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
58
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
59
+ s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
60
+ s.add_dependency(%q<rcov>, [">= 0"])
61
+ s.add_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
62
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
63
+ s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
64
+ s.add_dependency(%q<rcov>, [">= 0"])
65
+ end
66
+ else
67
+ s.add_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
68
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
69
+ s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
70
+ s.add_dependency(%q<rcov>, [">= 0"])
71
+ s.add_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
72
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
73
+ s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
74
+ s.add_dependency(%q<rcov>, [">= 0"])
75
+ end
76
+ end
77
+
data/spec/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,21 @@
1
+ require 'bundler'
2
+ begin
3
+ Bundler.setup(:default, :development)
4
+ rescue Bundler::BundlerError => e
5
+ $stderr.puts e.message
6
+ $stderr.puts "Run `bundle install` to install missing gems"
7
+ exit e.status_code
8
+ end
9
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
10
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
11
+ require 'topological_sort'
12
+ require 'rspec'
13
+ require 'rspec/autorun'
14
+
15
+ # Requires supporting files with custom matchers and macros, etc,
16
+ # in ./support/ and its subdirectories.
17
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
18
+
19
+ RSpec.configure do |config|
20
+
21
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe 'topological_sort' do
4
+ describe 'on an empty graph' do
5
+ it 'returns an empty list' do
6
+ topological_sort([]).should == []
7
+ end
8
+ end
9
+
10
+ describe 'on a double-star graph' do
11
+ before do
12
+ @graph = {1 => [2, 3, 4], 5 => [6, 7, 8]}
13
+ @roots = [1, 5]
14
+ end
15
+
16
+ it 'returns nodes in exit order' do
17
+ result = topological_sort(@roots) { |node| { :next => @graph[node] } }
18
+ result.should == [2, 3, 4, 1, 6, 7, 8, 5]
19
+ end
20
+
21
+ it 'uses node IDs if given' do
22
+ result = topological_sort(@roots) do |node|
23
+ { :id => node / 2, :next => @graph[node] }
24
+ end
25
+ result.should == [2, 4, 1]
26
+ end
27
+ end
28
+
29
+ describe 'on a hairy graph' do
30
+ before do
31
+ @graph = {1 => [2, 3, 4], 2 => [5, 6, 7], 3 => [6, 7, 8], 4 => [7, 8, 9]}
32
+ end
33
+
34
+ it 'returns nodes in exit order' do
35
+ result = topological_sort([1]) { |node| { :next => @graph[node] } }
36
+ result.should == [5, 6, 7, 2, 8, 3, 9, 4, 1]
37
+ end
38
+ end
39
+ end
metadata ADDED
@@ -0,0 +1,211 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: topological_sort
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Victor Costan
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-10-08 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ prerelease: false
23
+ name: rspec
24
+ version_requirements: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 62196421
30
+ segments:
31
+ - 2
32
+ - 0
33
+ - 0
34
+ - beta
35
+ - 19
36
+ version: 2.0.0.beta.19
37
+ requirement: *id001
38
+ type: :development
39
+ - !ruby/object:Gem::Dependency
40
+ prerelease: false
41
+ name: bundler
42
+ version_requirements: &id002 !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ hash: 23
48
+ segments:
49
+ - 1
50
+ - 0
51
+ - 0
52
+ version: 1.0.0
53
+ requirement: *id002
54
+ type: :development
55
+ - !ruby/object:Gem::Dependency
56
+ prerelease: false
57
+ name: jeweler
58
+ version_requirements: &id003 !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ~>
62
+ - !ruby/object:Gem::Version
63
+ hash: -1876988218
64
+ segments:
65
+ - 1
66
+ - 5
67
+ - 0
68
+ - pre3
69
+ version: 1.5.0.pre3
70
+ requirement: *id003
71
+ type: :development
72
+ - !ruby/object:Gem::Dependency
73
+ prerelease: false
74
+ name: rcov
75
+ version_requirements: &id004 !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ hash: 3
81
+ segments:
82
+ - 0
83
+ version: "0"
84
+ requirement: *id004
85
+ type: :development
86
+ - !ruby/object:Gem::Dependency
87
+ prerelease: false
88
+ name: rspec
89
+ version_requirements: &id005 !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ hash: 62196421
95
+ segments:
96
+ - 2
97
+ - 0
98
+ - 0
99
+ - beta
100
+ - 19
101
+ version: 2.0.0.beta.19
102
+ requirement: *id005
103
+ type: :development
104
+ - !ruby/object:Gem::Dependency
105
+ prerelease: false
106
+ name: bundler
107
+ version_requirements: &id006 !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ~>
111
+ - !ruby/object:Gem::Version
112
+ hash: 23
113
+ segments:
114
+ - 1
115
+ - 0
116
+ - 0
117
+ version: 1.0.0
118
+ requirement: *id006
119
+ type: :development
120
+ - !ruby/object:Gem::Dependency
121
+ prerelease: false
122
+ name: jeweler
123
+ version_requirements: &id007 !ruby/object:Gem::Requirement
124
+ none: false
125
+ requirements:
126
+ - - ~>
127
+ - !ruby/object:Gem::Version
128
+ hash: -1876988218
129
+ segments:
130
+ - 1
131
+ - 5
132
+ - 0
133
+ - pre3
134
+ version: 1.5.0.pre3
135
+ requirement: *id007
136
+ type: :development
137
+ - !ruby/object:Gem::Dependency
138
+ prerelease: false
139
+ name: rcov
140
+ version_requirements: &id008 !ruby/object:Gem::Requirement
141
+ none: false
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ hash: 3
146
+ segments:
147
+ - 0
148
+ version: "0"
149
+ requirement: *id008
150
+ type: :development
151
+ description: Generic implementation of DFS for topological sorting.
152
+ email: victor@costan.us
153
+ executables: []
154
+
155
+ extensions: []
156
+
157
+ extra_rdoc_files:
158
+ - LICENSE
159
+ - README.rdoc
160
+ files:
161
+ - .document
162
+ - .gitignore
163
+ - .project
164
+ - Gemfile
165
+ - Gemfile.lock
166
+ - LICENSE
167
+ - README.rdoc
168
+ - Rakefile
169
+ - VERSION
170
+ - lib/topological_sort.rb
171
+ - new.gemspec
172
+ - spec/.rspec
173
+ - spec/spec_helper.rb
174
+ - spec/topological_sort_spec.rb
175
+ has_rdoc: true
176
+ homepage: http://github.com/pwnall/new
177
+ licenses: []
178
+
179
+ post_install_message:
180
+ rdoc_options: []
181
+
182
+ require_paths:
183
+ - lib
184
+ required_ruby_version: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ hash: 3
190
+ segments:
191
+ - 0
192
+ version: "0"
193
+ required_rubygems_version: !ruby/object:Gem::Requirement
194
+ none: false
195
+ requirements:
196
+ - - ">="
197
+ - !ruby/object:Gem::Version
198
+ hash: 3
199
+ segments:
200
+ - 0
201
+ version: "0"
202
+ requirements: []
203
+
204
+ rubyforge_project:
205
+ rubygems_version: 1.3.7
206
+ signing_key:
207
+ specification_version: 3
208
+ summary: Topological sorting in arbitrary directed graphs.
209
+ test_files:
210
+ - spec/spec_helper.rb
211
+ - spec/topological_sort_spec.rb