combinatorics 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e0761711a88421b7b0214a3b585b6a843401bd1e84bb189c87a0c4167d7e5f32
4
+ data.tar.gz: 6c42e53311328f5d0f6c27ea339c3539046fee352dfb548155d35183a19d5aef
5
+ SHA512:
6
+ metadata.gz: 1d9df890fc1669969b84e48a0b3d6126111cc6e13369308f76c274e0227fcd475a9047872ef247dc83b009f4b5d234526aa9d88c0c59cff7c9129d080c93a044
7
+ data.tar.gz: 53eabbc7025dbaa9e79d8fe44c8d68c0182de3b575f425f6b4d0231c88920a8ee7b8c85bfd8f94743b8a618184525d0db5264d37232bd8793396b93afbfb1a0f
@@ -0,0 +1,28 @@
1
+ name: CI
2
+
3
+ on: [ push, pull_request ]
4
+
5
+ jobs:
6
+ tests:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ ruby:
12
+ - 2.6
13
+ - 2.7
14
+ - '3.0'
15
+ - 3.1
16
+ - jruby
17
+ - truffleruby
18
+ name: Ruby ${{ matrix.ruby }}
19
+ steps:
20
+ - uses: actions/checkout@v2
21
+ - name: Set up Ruby
22
+ uses: ruby/setup-ruby@v1
23
+ with:
24
+ ruby-version: ${{ matrix.ruby }}
25
+ - name: Install dependencies
26
+ run: bundle install --jobs 4 --retry 3
27
+ - name: Run tests
28
+ run: bundle exec rake test
data/.gitignore CHANGED
@@ -1,8 +1,7 @@
1
- pkg
2
- doc
3
- web
4
- tmp
1
+ /Gemfile.lock
2
+ /pkg
3
+ /doc
4
+ /.yardoc
5
5
  .DS_Store
6
- .yardoc
7
6
  *.swp
8
7
  *~
data/ChangeLog.md CHANGED
@@ -1,3 +1,8 @@
1
+ ### 0.4.4 / 2022-01-16
2
+
3
+ * Fixed a bug in {Combinatorics::Choose.cardinality} for when `0`
4
+ is given and `0` was returned instead of `1`.
5
+
1
6
  ### 0.4.3 / 2012-05-28
2
7
 
3
8
  * Fixed a typo in the gemspec, which incorrectly set
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'rake'
7
+ gem 'rubygems-tasks', '~> 0.2'
8
+
9
+ gem 'rspec', '~> 3.0'
10
+
11
+ gem 'kramdown'
12
+ gem 'yard', '~> 0.9'
13
+ gem 'yard-spellcheck', require: false
14
+ end
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-2012 Hal Brodigan
1
+ Copyright (c) 2010-2022 Hal Brodigan
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,15 +1,17 @@
1
1
  # Combinatorics
2
2
 
3
+ [![CI](https://github.com/postmodern/combinatorics/actions/workflows/ruby.yml/badge.svg)](https://github.com/postmodern/combinatorics/actions/workflows/ruby.yml)
4
+ [![Code Climate](https://codeclimate.com/github/postmodern/combinatorics.svg)](https://codeclimate.com/github/postmodern/combinatorics)
5
+
3
6
  * [Source](https://github.com/postmodern/combinatorics)
4
7
  * [Issues](https://github.com/postmodern/combinatorics/issues)
5
8
  * [Documentation](http://rubydoc.info/gems/combinatorics)
6
- * [Email](mailto:postmodern.mod3 at gmail.com)
7
9
 
8
10
  ## Description
9
11
 
10
12
  A collection of modules and methods for performing
11
13
  [Combinatoric](http://en.wikipedia.org/wiki/Combinatoric) calculations.
12
- Methods are defined to compute power sets, cartesian products, permutations,
14
+ Methods are defined to compute power sets, Cartesian products, permutations,
13
15
  combinations, and derangements.
14
16
 
15
17
  Note: this includes k-combinations and k-permutations, i.e. only generating
@@ -22,134 +24,169 @@ never complete due to exponential computational complexity.)
22
24
 
23
25
  ## Features
24
26
 
25
- * Adds Haskell/Python style list comprehensions via {Array#comprehension}.
27
+ * Adds Haskell/Python style list comprehensions via [Array#comprehension].
26
28
  * Provides reusable Combinatorics Mixins:
27
- * {Combinatorics::CartesianProduct}
28
- * {Combinatorics::Choose}
29
- * {Combinatorics::Derange}
30
- * {Combinatorics::Permute}
31
- * {Combinatorics::PowerSet}
32
- * Adds Combinatorics conveniance methods to {Array} and {Set}:
33
- * `cartesian_product`
34
- * `choose`
35
- * `derange`
36
- * `permute`
37
- * `powerset`
38
- * Adds conveniance methods:
39
- * {Range#&}
40
- * {Range#upto}
41
- * {Range#downto}
42
- * {Math.sigma}
43
- * {Math.pi}
44
- * {Math.factorial}
45
- * {Math.subfactorial}
29
+ * [Combinatorics::CartesianProduct]
30
+ * [Combinatorics::Choose]
31
+ * [Combinatorics::Derange]
32
+ * [Combinatorics::Permute]
33
+ * [Combinatorics::PowerSet]
34
+ * Adds Combinatorics core extension methods to {Array} and {Set}:
35
+ * [cartesian_product]
36
+ * [choose]
37
+ * [derange]
38
+ * [permute]
39
+ * [powerset]
40
+ * Adds additional core extension methods:
41
+ * [Range#&]
42
+ * [Range#upto]
43
+ * [Range#downto]
44
+ * [Math.sigma]
45
+ * [Math.pi]
46
+ * [Math.factorial]
47
+ * [Math.subfactorial]
48
+
49
+ [Array#comprehension]: https://rubydoc.info/gems/combinatorics/Array#comprehension-instance_method
50
+ [Combinatorics::CartesianProduct]: https://rubydoc.info/gems/combinatorics/Combinatorics/CartesianProduct
51
+ [Combinatorics::Choose]: https://rubydoc.info/gems/combinatorics/Combinatorics/Choose
52
+ [Combinatorics::Derange]: https://rubydoc.info/gems/combinatorics/Combinatorics/Derange
53
+ [Combinatorics::Permute]: https://rubydoc.info/gems/combinatorics/Combinatorics/Permute
54
+ [Combinatorics::PowerSet]: https://rubydoc.info/gems/combinatorics/Combinatorics/PowerSet
55
+ [cartesian_product]: https://rubydoc.info/gems/combinatorics/Combinatorics/CartesianProduct/Mixin#cartesian_product-instance_method
56
+ [choose]: https://rubydoc.info/gems/combinatorics/Combinatorics/Choose/Mixin#choose-instance_method
57
+ [derange]: https://rubydoc.info/gems/combinatorics/Combinatorics/Derange/Mixin#derange-instance_method
58
+ [permute]: https://rubydoc.info/gems/combinatorics/Combinatorics/Permute/Mixin#permute-instance_method
59
+ [powerset]: https://rubydoc.info/gems/combinatorics/Combinatorics/PowerSet/Mixin#powerset-instance_method
60
+ [Range#&]: https://rubydoc.info/gems/combinatorics/Range#&-instance_method
61
+ [Range#upto]: https://rubydoc.info/gems/combinatorics/Range#upto-instance_method
62
+ [Range#downto]: https://rubydoc.info/gems/combinatorics/Range#downto-instance_method
63
+ [Math.sigma]: https://rubydoc.info/gems/combinatorics/Math#sigma-class_method
64
+ [Math.pi]: https://rubydoc.info/gems/combinatorics/Math#pi-class_method
65
+ [Math.factorial]: https://rubydoc.info/gems/combinatorics/Math#factorial-class_method
66
+ [Math.subfactorial]: https://rubydoc.info/gems/combinatorics/Math#subfactorial-class_method
46
67
 
47
68
  ## Examples
48
69
 
49
70
  Power-set:
50
71
 
51
- Set['ab', 'cd', 'ef'].powerset
52
- # => [#<Set: {}>,
53
- #<Set: {"ef"}>,
54
- #<Set: {"cd"}>,
55
- #<Set: {"cd", "ef"}>,
56
- #<Set: {"ab"}>,
57
- #<Set: {"ab", "ef"}>,
58
- #<Set: {"ab", "cd"}>,
59
- #<Set: {"ab", "cd", "ef"}>]
72
+ ```ruby
73
+ Set['ab', 'cd', 'ef'].powerset
74
+ # => [#<Set: {}>,
75
+ #<Set: {"ef"}>,
76
+ #<Set: {"cd"}>,
77
+ #<Set: {"cd", "ef"}>,
78
+ #<Set: {"ab"}>,
79
+ #<Set: {"ab", "ef"}>,
80
+ #<Set: {"ab", "cd"}>,
81
+ #<Set: {"ab", "cd", "ef"}>]
82
+ ```
60
83
 
61
84
  Cartesian products:
62
85
 
63
- require 'combinatorics/cartesian_product'
64
-
65
- ['a', 'b', 'c'].cartesian_product([0, 1, 2]).to_a
66
- # => [["a", 0],
67
- ["b", 0],
68
- ["c", 0],
69
- ["a", 1],
70
- ["b", 1],
71
- ["c", 1],
72
- ["a", 2],
73
- ["b", 2],
74
- ["c", 2]]
86
+ ```ruby
87
+ require 'combinatorics/cartesian_product'
88
+
89
+ ['a', 'b', 'c'].cartesian_product([0, 1, 2]).to_a
90
+ # => [["a", 0],
91
+ ["b", 0],
92
+ ["c", 0],
93
+ ["a", 1],
94
+ ["b", 1],
95
+ ["c", 1],
96
+ ["a", 2],
97
+ ["b", 2],
98
+ ["c", 2]]
99
+ ```
75
100
 
76
101
  k-combinations:
77
102
 
78
- require 'combinatorics/choose'
79
-
80
- ('a'..'f').to_a.choose(2).to_a
81
- # => [["a", "b"],
82
- ["a", "c"],
83
- ["a", "d"],
84
- ["a", "e"],
85
- ["a", "f"],
86
- ["b", "c"],
87
- ["b", "d"],
88
- ["b", "e"],
89
- ["b", "f"],
90
- ["c", "d"],
91
- ["c", "e"],
92
- ["c", "f"],
93
- ["d", "e"],
94
- ["d", "f"],
95
- ["e", "f"]]
103
+ ```ruby
104
+ require 'combinatorics/choose'
105
+
106
+ ('a'..'f').to_a.choose(2).to_a
107
+ # => [["a", "b"],
108
+ ["a", "c"],
109
+ ["a", "d"],
110
+ ["a", "e"],
111
+ ["a", "f"],
112
+ ["b", "c"],
113
+ ["b", "d"],
114
+ ["b", "e"],
115
+ ["b", "f"],
116
+ ["c", "d"],
117
+ ["c", "e"],
118
+ ["c", "f"],
119
+ ["d", "e"],
120
+ ["d", "f"],
121
+ ["e", "f"]]
122
+ ```
96
123
 
97
124
  Derangements:
98
125
 
99
- require 'combinatorics/derange'
100
-
101
- [:_, :q, :z, :x].derange.to_a
102
- # => [[:q, :_, :x, :z],
103
- [:q, :z, :x, :_],
104
- [:q, :x, :_, :z],
105
- [:z, :_, :x, :q],
106
- [:z, :x, :_, :q],
107
- [:z, :x, :q, :_],
108
- [:x, :_, :q, :z],
109
- [:x, :z, :_, :q],
110
- [:x, :z, :q, :_]]
126
+ ```ruby
127
+ require 'combinatorics/derange'
128
+
129
+ [:_, :q, :z, :x].derange.to_a
130
+ # => [[:q, :_, :x, :z],
131
+ [:q, :z, :x, :_],
132
+ [:q, :x, :_, :z],
133
+ [:z, :_, :x, :q],
134
+ [:z, :x, :_, :q],
135
+ [:z, :x, :q, :_],
136
+ [:x, :_, :q, :z],
137
+ [:x, :z, :_, :q],
138
+ [:x, :z, :q, :_]]
139
+ ```
111
140
 
112
141
  Permutation cardinality:
113
142
 
114
- require 'combinatorics/permutation'
115
-
116
- Combinatorics::Permute.cardinality(128)
117
- # => 8256
143
+ ```ruby
144
+ require 'combinatorics/permutation'
145
+
146
+ Combinatorics::Permute.cardinality(128)
147
+ # => 8256
148
+ ```
118
149
 
119
150
  List comprehensions:
120
151
 
121
- require 'combinatorics/list_comprehension'
122
-
123
- [(0..10).step(2),('a'..'c')].comprehension.to_a
124
- # => [[0, "a"],
125
- [0, "b"],
126
- [0, "c"],
127
- [2, "a"],
128
- [2, "b"],
129
- [2, "c"],
130
- [4, "a"],
131
- [4, "b"],
132
- [4, "c"],
133
- [6, "a"],
134
- [6, "b"],
135
- [6, "c"],
136
- [8, "a"],
137
- [8, "b"],
138
- [8, "c"],
139
- [10, "a"],
140
- [10, "b"],
141
- [10, "c"]]
152
+ ```ruby
153
+ require 'combinatorics/list_comprehension'
154
+
155
+ [(0..10).step(2),('a'..'c')].comprehension.to_a
156
+ # => [[0, "a"],
157
+ [0, "b"],
158
+ [0, "c"],
159
+ [2, "a"],
160
+ [2, "b"],
161
+ [2, "c"],
162
+ [4, "a"],
163
+ [4, "b"],
164
+ [4, "c"],
165
+ [6, "a"],
166
+ [6, "b"],
167
+ [6, "c"],
168
+ [8, "a"],
169
+ [8, "b"],
170
+ [8, "c"],
171
+ [10, "a"],
172
+ [10, "b"],
173
+ [10, "c"]]
174
+ ```
142
175
 
143
176
  Find the intersecting sub-range between two ranges:
144
177
 
145
- (1..50) & (20..100)
146
- # => (20..50)
178
+ ```ruby
179
+ (1..50) & (20..100)
180
+ # => (20..50)
181
+ ```
147
182
 
148
183
  Enumerate over every sub-range between two ranges:
149
184
 
150
- (1..5).upto(2..10).to_a
151
- # => [1..5, 1..6, 1..7, 1..8, 1..9, 1..10,
152
- 2..5, 2..6, 2..7, 2..8, 2..9, 2..10]
185
+ ```ruby
186
+ (1..5).upto(2..10).to_a
187
+ # => [1..5, 1..6, 1..7, 1..8, 1..9, 1..10,
188
+ 2..5, 2..6, 2..7, 2..8, 2..9, 2..10]
189
+ ```
153
190
 
154
191
  ## Requirements
155
192
 
@@ -157,10 +194,12 @@ Enumerate over every sub-range between two ranges:
157
194
 
158
195
  ## Install
159
196
 
160
- $ gem install combinatorics
197
+ ```shell
198
+ $ gem install combinatorics
199
+ ```
161
200
 
162
201
  ## Copyright
163
202
 
164
- Copyright (c) 2010-2012 Hal Brodigan
203
+ Copyright (c) 2010-2022 Hal Brodigan
165
204
 
166
205
  See {file:LICENSE.txt} for license information.
data/Rakefile CHANGED
@@ -1,39 +1,15 @@
1
1
  require 'rubygems'
2
- require 'rake'
3
2
 
4
- begin
5
- gem 'rubygems-tasks', '~> 0.1'
6
- require 'rubygems/tasks'
3
+ require 'rubygems/tasks'
4
+ Gem::Tasks.new
7
5
 
8
- Gem::Tasks.new
9
- rescue LoadError => e
10
- warn e.message
11
- warn "Run `gem install rubygems-tasks` to install 'rubygems/tasks'."
12
- end
13
-
14
- begin
15
- gem 'rspec', '~> 2.4'
16
- require 'rspec/core/rake_task'
17
-
18
- RSpec::Core::RakeTask.new
19
- rescue LoadError => e
20
- task :spec do
21
- abort "Please run `gem install rspec` to install RSpec."
22
- end
23
- end
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new
24
8
  task :test => :spec
25
9
  task :default => :spec
26
10
 
27
- begin
28
- gem 'yard', '~> 0.7'
29
- require 'yard'
30
-
31
- YARD::Rake::YardocTask.new
32
- rescue LoadError => e
33
- task :yard do
34
- abort "Please run `gem install yard` to install YARD."
35
- end
36
- end
11
+ require 'yard'
12
+ YARD::Rake::YardocTask.new
37
13
 
38
14
  task :benchmark do
39
15
  Dir.glob('benchmarks/*.rb') { |script| ruby(script) }
@@ -20,6 +20,7 @@ Gem::Specification.new do |gem|
20
20
  gem.authors = Array(gemspec['authors'])
21
21
  gem.email = gemspec['email']
22
22
  gem.homepage = gemspec['homepage']
23
+ gem.metadata = gemspec['metadata'] if gemspec['metadata']
23
24
 
24
25
  glob = lambda { |patterns| gem.files & Dir[*patterns] }
25
26
 
data/gemspec.yml CHANGED
@@ -13,9 +13,13 @@ email:
13
13
  homepage: https://github.com/postmodern/combinatorics#readme
14
14
  has_yard: true
15
15
 
16
+ metadata:
17
+ documentation_uri: https://rubydoc.info/gems/combinatorics
18
+ source_code_uri: https://github.com/postmodern/combinatorics.rb
19
+ bug_tracker_uri: https://github.com/postmodern/combinatorics.rb/issues
20
+ changelog_uri: https://github.com/postmodern/combinatorics.rb/blob/master/ChangeLog.md
21
+
16
22
  required_ruby_version: ">= 1.8.7"
17
23
 
18
24
  development_dependencies:
19
- rubygems-tasks: ~> 0.1
20
- rspec: ~> 2.4
21
- yard: ~> 0.7
25
+ bundler: ~> 2.0
@@ -38,7 +38,7 @@ module Combinatorics
38
38
  raise(RangeError,"n must be non-negative") if n < 0
39
39
 
40
40
  case r
41
- when 0 then 0
41
+ when 0 then 1
42
42
  when nil then Math.factorial(n)
43
43
  else
44
44
  Math.factorial(n) / (Math.factorial(r) * Math.factorial(n - r))
@@ -5,7 +5,7 @@ module Combinatorics
5
5
  # auto-detects the `Generator` class.
6
6
  Generator = if defined?(::Generator) # 1.8.7
7
7
  ::Generator
8
- elsif defined?(::Enumerator::Generator) # 1.9
8
+ elsif defined?(::Enumerator::Generator) # >= 1.9.1
9
9
  ::Enumerator::Generator
10
10
  else
11
11
  raise(NameError,"unable to find the Generator class")
@@ -1,4 +1,4 @@
1
1
  module Combinatorics
2
2
  # Combinatorics module revision number
3
- VERSION = '0.4.3'
3
+ VERSION = '0.4.4'
4
4
  end
@@ -6,55 +6,55 @@ describe CartesianProduct do
6
6
 
7
7
  describe "cardinality" do
8
8
  it "should return 1 for cardinality(1, 1)" do
9
- subject.cardinality(1, 1).should == 1
9
+ expect(subject.cardinality(1, 1)).to eq(1)
10
10
  end
11
11
 
12
12
  it "should return 2 for cardinality(1, 2)" do
13
- subject.cardinality(1, 2).should == 2
13
+ expect(subject.cardinality(1, 2)).to eq(2)
14
14
  end
15
15
 
16
16
  it "should return 2 for cardinality(2, 1)" do
17
- subject.cardinality(2, 1).should == 2
17
+ expect(subject.cardinality(2, 1)).to eq(2)
18
18
  end
19
19
 
20
20
  it "should return 4 for cardinality(2, 2)" do
21
- subject.cardinality(2, 2).should == 4
21
+ expect(subject.cardinality(2, 2)).to eq(4)
22
22
  end
23
23
 
24
24
  it "should return 3 for cardinality(3, 1)" do
25
- subject.cardinality(3, 1).should == 3
25
+ expect(subject.cardinality(3, 1)).to eq(3)
26
26
  end
27
27
 
28
28
  it "should return 3 for cardinality(1, 3)" do
29
- subject.cardinality(1, 3).should == 3
29
+ expect(subject.cardinality(1, 3)).to eq(3)
30
30
  end
31
31
 
32
32
  it "should return 6 for cardinality(2, 3)" do
33
- subject.cardinality(2, 3).should == 6
33
+ expect(subject.cardinality(2, 3)).to eq(6)
34
34
  end
35
35
 
36
36
  it "should return 6 for cardinality(3, 2)" do
37
- subject.cardinality(3, 2).should == 6
37
+ expect(subject.cardinality(3, 2)).to eq(6)
38
38
  end
39
39
 
40
40
  it "should return 9 for cardinality(3, 3)" do
41
- subject.cardinality(3, 3).should == 9
41
+ expect(subject.cardinality(3, 3)).to eq(9)
42
42
  end
43
43
 
44
44
  it "should raise RangeError if c1 is negative" do
45
- lambda { subject.cardinality(-1, 1) }.should raise_error(RangeError)
45
+ expect { subject.cardinality(-1, 1) }.to raise_error(RangeError)
46
46
  end
47
47
 
48
48
  it "should raise RangeError if c2 is negative" do
49
- lambda { subject.cardinality(1, -1) }.should raise_error(RangeError)
49
+ expect { subject.cardinality(1, -1) }.to raise_error(RangeError)
50
50
  end
51
51
 
52
52
  it "should raise RangeError if c1 is zero" do
53
- lambda { subject.cardinality(0, 1) }.should raise_error(RangeError)
53
+ expect { subject.cardinality(0, 1) }.to raise_error(RangeError)
54
54
  end
55
55
 
56
56
  it "should raise RangeError if c2 is zero" do
57
- lambda { subject.cardinality(1, 0) }.should raise_error(RangeError)
57
+ expect { subject.cardinality(1, 0) }.to raise_error(RangeError)
58
58
  end
59
59
  end
60
60