topological_sort 0.1.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.
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