combinatorics 0.4.3 → 0.4.4

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