signed_multiset 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 09a3ae9f761ec896d77d62a7a691f9fe65a20f09
4
+ data.tar.gz: 0f66bdd5eb798fece35bcd588bc90a50e1c22d81
5
+ SHA512:
6
+ metadata.gz: a30b92054d69d03ebfa1947fd8505f81ce57d7f1230095ec2ffff274910232a26596c8af4df9bfba87cacaab441e6704cc9b1fcde7477969b4411282628dc382
7
+ data.tar.gz: 45684d6839b35ffe4c26073fd4d026064b2aa251ef8aee35eb07c1408ab1b4cfbf97d3e073dd2f4d098861a05247c64c4b8bbea4dfeeb3233ce5814ce3b3dd89
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1 @@
1
+ 2.0.0-p195
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in signed_multiset.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Josh Lewis
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,65 @@
1
+ # signed_multiset
2
+
3
+ [![Build Status](https://travis-ci.org/joshwlewis/signed_multiset.png?branch=master)](https://travis-ci.org/joshwlewis/signed_multiset)
4
+ [![Code Climate](https://codeclimate.com/github/joshwlewis/signed_multiset.png)](https://codeclimate.com/github/joshwlewis/signed_multiset)
5
+ [![Dependency Status](https://gemnasium.com/joshwlewis/signed_multiset.png)](https://gemnasium.com/joshwlewis/signed_multiset)
6
+
7
+ Signed Multiset is a Ruby implementation of a Multiset that allows negative membership.
8
+
9
+ You can think of it as a Multiset or Bag that allows for negative counts. It feels like a Ruby Hash or Array, but with some differences:
10
+
11
+ - A key (any ruby object) can be added to or removed from the Multiset any number of times, and is referred to as it's multiplicity
12
+
13
+ - A key can only be considered a member of the Signed Multiset if it's multiplicity is not 0. Setting it's multiplicity to 0 effectively removes that item from the SignedMultiset.
14
+
15
+ - The size or length of a SignedMultiset is the number of unique keys with non-zero multiplicities.
16
+
17
+ - The cardinality or sum of a SignedMultiset is the total sum of the multiplicities.
18
+
19
+ For theory and proofs, refer to [Negative Membership](http://projecteuclid.org/DPubS/Repository/1.0/Disseminate?view=body&id=pdf_1&handle=euclid.ndjfl/1093635499) by Wayne D. Blizard.
20
+
21
+ ## Installation
22
+
23
+ Add this line to your application's Gemfile:
24
+
25
+ gem 'signed_multiset'
26
+
27
+ And then execute:
28
+
29
+ $ bundle
30
+
31
+ Or install it yourself as:
32
+
33
+ $ gem install signed_multiset
34
+
35
+ ## Usage
36
+
37
+ ```ruby
38
+ require 'signed_multiset'
39
+
40
+ s = SignedMultiset.new(a: 1, b: 2, c: 3)
41
+ #=> => <SignedMultiset a: 1, b: 2, c: 3>
42
+
43
+ s[:b]
44
+ #=> 2
45
+
46
+ s[:d] = -4
47
+ #=> -4
48
+
49
+ s << :d
50
+ #=> <SignedMultiset a: 1, b: 2, c: 3, d: -3>
51
+
52
+ s.increment(a, -1)
53
+ #=> 0
54
+
55
+ s[:a]
56
+ #=> nil
57
+ ```
58
+
59
+ ## Contributing
60
+
61
+ 1. Fork it
62
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
63
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
64
+ 4. Push to the branch (`git push origin my-new-feature`)
65
+ 5. Create new Pull Request
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ t.pattern = "test/**/*_test.rb"
7
+ t.verbose = true
8
+ end
9
+
10
+ task default: [:test]
@@ -0,0 +1,2 @@
1
+ require "signed_multiset/version"
2
+ require "signed_multiset/signed_multiset"
@@ -0,0 +1,198 @@
1
+ class SignedMultiset
2
+
3
+ include Enumerable
4
+ include Comparable
5
+
6
+ # Create a new instance with a list of objects.
7
+ #
8
+ # @param *list [Object] A list of objects to add to the set
9
+ def self.[](*list)
10
+ new(list)
11
+ end
12
+
13
+ # Create a new SignedMultiset instance.
14
+ #
15
+ # @param object [Enumerable, nil] An array of keys, or key-muliplicity pairs.
16
+ def initialize(object=nil)
17
+ if object.is_a?(Enumerable)
18
+ object.each { |k, v| increment(k, v || 1) }
19
+ end
20
+ end
21
+
22
+ # Get the non-zero key-multiplicity pairs.
23
+ #
24
+ # @return [Hash]
25
+ def multiplicities
26
+ entries.delete_if{|k,v| v == 0}
27
+ end
28
+
29
+ # Iterate over the multiplicity collection.
30
+ #
31
+ # @return [Enumerator]
32
+ def each(*args, &block)
33
+ if block_given?
34
+ multiplicities.each { |k,v| yield(k,v) }
35
+ else
36
+ multiplicities.each(args)
37
+ end
38
+ end
39
+
40
+ # Get the multiplicity for a key.
41
+ #
42
+ # @param key [Object] The key to get the multiplicity of
43
+ # @return [Integer, nil] The multiplicity for the key, or nil if the key is
44
+ # not present, or has a zero multiplicity
45
+ def [](key)
46
+ multiplicities[key]
47
+ end
48
+
49
+ # Set the multiplicity for a key.
50
+ #
51
+ # @param key [Object] The key to set the multiplicity of
52
+ # @param multiplicity [Integer] The desired multiplicity
53
+ # @return [Integer] The multiplicity for the key
54
+ def []=(key, multiplicity)
55
+ entries[key] = multiplicity
56
+ multiplicities[key]
57
+ end
58
+
59
+ # Increment the multiplicity for a key.
60
+ #
61
+ # @param key (see #[]=)
62
+ # @param value [Integer] The desired increment value, positive or negative
63
+ # @return (see #[]=)
64
+ def increment(key, value)
65
+ entries[key] ||= 0
66
+ entries[key] += value
67
+ end
68
+
69
+ # Increment multiplicity by 1 for a key. This method is chainable.
70
+ #
71
+ # @param key [Object] The key to increment the multiplicity of
72
+ # @return [self]
73
+ def <<(key)
74
+ increment(key, 1)
75
+ self
76
+ end
77
+
78
+ # Creates a new instance of equal to current instance
79
+ # @return [SignedMultiset]
80
+ def dup
81
+ self.class.new(multiplicities)
82
+ end
83
+
84
+ # Combine self with another SignedMultiset via addition to create a merged instance.
85
+ #
86
+ # @param other [SignedMultiset]
87
+ # @return [SignedMultiset]
88
+ def +(other)
89
+ other.multiplicities.reduce(self.dup) do |m, (k, v)|
90
+ m.increment(k,v); m
91
+ end
92
+ end
93
+
94
+ # Combine self with another SignedMultiset via subtraction to create a merged instance.
95
+ #
96
+ # @param other (see #+)
97
+ # @return (see #+)
98
+ def -(other)
99
+ other.multiplicities.reduce(self.dup) do |m, (k, v)|
100
+ m.increment(k,-v); m
101
+ end
102
+ end
103
+
104
+ # Combine self with another SignedMultiset via union to create a merged instance.
105
+ #
106
+ # @param other (see #+)
107
+ # @return (see #+)
108
+ def |(other)
109
+ (keys | other.keys).reduce(self.class.new) do |m, k|
110
+ m.increment(k, [self[k] || 0, other[k] || 0].max); m
111
+ end
112
+ end
113
+
114
+ # Combine self with another SignedMultiset via intersection to create a merged instance.
115
+ #
116
+ # @param other (see #+)
117
+ # @return (see #+)
118
+ def &(other)
119
+ (keys & other.keys).reduce(self.class.new) do |m, k|
120
+ value = [self[k], other[k]].min
121
+ m.increment(k, value); m
122
+ end
123
+ end
124
+
125
+ # Get the list of keys for self.
126
+ #
127
+ # @return [Array]
128
+ def keys
129
+ multiplicities.keys
130
+ end
131
+
132
+ # Get the multiplicity values for self.
133
+ #
134
+ # @return [Array]
135
+ def values
136
+ multiplicities.values
137
+ end
138
+
139
+ # Get the cardinality (sum of multiplicities) for self.
140
+ #
141
+ # @return [Integer]
142
+ def cardinality
143
+ values.inject(&:+)
144
+ end
145
+ alias_method :sum, :cardinality
146
+
147
+ # Get the count of unique keys in the SignedMultiset.
148
+ #
149
+ # @return [Integer]
150
+ def size
151
+ keys.size
152
+ end
153
+ alias_method :length, :size
154
+
155
+ # Compare self with another SignedMultiset
156
+ #
157
+ # @param other (see #+)
158
+ # @return [-1,0,1]
159
+ def <=>(other)
160
+ if [:multiplicities, :cardinality, :size].all? { |m| other.respond_to?(m) }
161
+ if multiplicities == other.multiplicities
162
+ 0
163
+ elsif cardinality != other.cardinality
164
+ cardinality <=> other.cardinality
165
+ elsif size != other.size
166
+ size <=> other.size
167
+ else
168
+ multiplicities <=> other.multiplicities
169
+ end
170
+ end
171
+ end
172
+
173
+ def to_hash
174
+ multiplicities.dup
175
+ end
176
+
177
+ def to_a
178
+ multiplicities.to_a
179
+ end
180
+
181
+ def to_s
182
+ multiplicities.map{ |k,c| "#{k}: #{c}"}.join(', ')
183
+ end
184
+
185
+ def inspect
186
+ "<SignedMultiset #{to_s}>"
187
+ end
188
+
189
+ private
190
+
191
+ # Get the key-multiplicity pairs (even those with zero multiplicities).
192
+ #
193
+ # @return [Hash]
194
+ def entries
195
+ @entries ||= {}
196
+ end
197
+
198
+ end
@@ -0,0 +1,3 @@
1
+ class SignedMultiset
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'signed_multiset/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "signed_multiset"
8
+ spec.version = SignedMultiset::VERSION
9
+ spec.authors = ["Josh Lewis"]
10
+ spec.email = ["josh.w.lewis@gmail.com"]
11
+ spec.description = %q{Multisets with negative membership}
12
+ spec.summary = %q{Signed Multiset is a Ruby implementation of a Multiset that allows negative membership. You can think of it as a Multiset or Bag that allows for negative counts. It feels like a Ruby Hash or Array, but with some differences.}
13
+ spec.homepage = "http://github.com/joshwlewis/signed_multiset"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "minitest"
24
+
25
+ end
@@ -0,0 +1,196 @@
1
+ require 'test_helper'
2
+
3
+ describe SignedMultiset do
4
+ subject { SignedMultiset.new(foo: 4, bar: 2, baz: 0) }
5
+ let(:other){ SignedMultiset.new(foo: -3, qux: 2) }
6
+
7
+ describe "#initialize" do
8
+ it "must accept a hash" do
9
+ subject.keys.must_equal([:foo, :bar])
10
+ end
11
+ it "must accept no arguments" do
12
+ set = SignedMultiset.new
13
+ set.keys.must_equal([])
14
+ end
15
+ it "must accept an Array" do
16
+ set = SignedMultiset.new([:a, :b, :c, :a, :b])
17
+ set.keys.must_equal([:a, :b, :c])
18
+ end
19
+ it "must accept a SignedMultiset" do
20
+ set = SignedMultiset.new(subject)
21
+ set.keys.must_equal([:foo, :bar])
22
+ end
23
+ end
24
+
25
+ describe "::[]" do
26
+ it "must create a new set" do
27
+ set = SignedMultiset[:a, :b, :b, :c]
28
+ set.keys.must_equal([:a, :b, :c])
29
+ end
30
+ end
31
+
32
+ describe "multiplicities" do
33
+ it "must be an Enumerable" do
34
+ subject.multiplicities.must_be_kind_of(Enumerable)
35
+ end
36
+ it "should delete keys with zero multiplicitys" do
37
+ subject.multiplicities.keys.must_equal([:foo, :bar])
38
+ end
39
+ end
40
+
41
+ describe "#[]" do
42
+ it "must find existing keys and return multiplicity" do
43
+ subject[:foo].must_equal(4)
44
+ subject[:bar].must_equal(2)
45
+ end
46
+ it "must return nil for missing keys" do
47
+ subject[:qux].must_be_nil
48
+ end
49
+ it "must return nil for keys with zero multiplicitys" do
50
+ subject[:bax].must_be_nil
51
+ end
52
+ end
53
+
54
+ describe "#[]=" do
55
+ it "must set multiplicity for exisiting keys" do
56
+ subject[:foo].must_equal(4)
57
+ subject[:foo] = -1
58
+ subject[:foo].must_equal(-1)
59
+ end
60
+
61
+ it "must increment key and set multiplicity for new keys" do
62
+ subject[:baz].must_be_nil
63
+ subject[:baz] = 3
64
+ subject[:baz].must_equal(3)
65
+ end
66
+ end
67
+
68
+ describe "increment" do
69
+ it "should increment existing keys" do
70
+ subject[:bar].must_equal(2)
71
+ subject.increment(:bar, -4)
72
+ subject[:bar].must_equal(-2)
73
+ end
74
+ it "should increment new keys" do
75
+ subject[:qux].must_be_nil
76
+ subject.increment(:qux, 2)
77
+ subject[:qux].must_equal(2)
78
+ end
79
+ end
80
+
81
+ describe "<<" do
82
+ it "should increment existing keys" do
83
+ subject[:bar].must_equal(2)
84
+ subject << :bar
85
+ subject[:bar].must_equal(3)
86
+ end
87
+ it "should increment new keys" do
88
+ subject[:qux].must_be_nil
89
+ subject << :qux
90
+ subject[:qux].must_equal(1)
91
+ end
92
+ it "should be chainable" do
93
+ subject << :foo << :baz << :foo
94
+ subject[:foo].must_equal(6)
95
+ subject[:baz].must_equal(1)
96
+ end
97
+ end
98
+
99
+ describe "#+" do
100
+ let(:merged) { subject + other }
101
+ it "should return a new set" do
102
+ merged.must_be_instance_of(SignedMultiset)
103
+ merged.wont_equal(subject)
104
+ merged.wont_equal(other)
105
+ end
106
+ it "should sum the keys" do
107
+ merged[:foo].must_equal(1)
108
+ merged[:bar].must_equal(2)
109
+ merged[:qux].must_equal(2)
110
+ end
111
+ end
112
+
113
+ describe "#-" do
114
+ let(:merged) { subject - other }
115
+ it "should return a new set" do
116
+ merged.must_be_instance_of(SignedMultiset)
117
+ merged.wont_equal(subject)
118
+ merged.wont_equal(other)
119
+ end
120
+ it "should sum the keys" do
121
+ merged[:foo].must_equal(7)
122
+ merged[:bar].must_equal(2)
123
+ merged[:qux].must_equal(-2)
124
+ end
125
+ end
126
+
127
+ describe "#&" do
128
+ let(:merged) { subject & other }
129
+ it "should reutrn a new set" do
130
+ subject.must_be_instance_of(SignedMultiset)
131
+ merged.wont_equal(subject)
132
+ merged.wont_equal(other)
133
+ end
134
+ it "should return the intersection" do
135
+ merged[:foo].must_equal(-3)
136
+ merged[:bar].must_be_nil
137
+ merged[:baz].must_be_nil
138
+ merged[:qux].must_be_nil
139
+ end
140
+ end
141
+
142
+ describe "#|" do
143
+ let(:merged) { subject | other }
144
+ it "should reutrn a new set" do
145
+ subject.must_be_instance_of(SignedMultiset)
146
+ merged.wont_equal(subject)
147
+ merged.wont_equal(other)
148
+ end
149
+ it "should return the union" do
150
+ merged[:foo].must_equal(4)
151
+ merged[:bar].must_equal(2)
152
+ merged[:baz].must_be_nil
153
+ merged[:qux].must_equal(2)
154
+ end
155
+ end
156
+
157
+ describe "#to_hash" do
158
+ it "should return a hash" do
159
+ subject.to_hash.must_equal(foo: 4, bar: 2)
160
+ end
161
+ end
162
+
163
+ describe "#to_a" do
164
+ it "should return an Array" do
165
+ subject.to_a.must_equal([[:foo, 4], [:bar, 2]])
166
+ end
167
+ end
168
+
169
+ describe "#cardinality" do
170
+ it "should return the total of all multiplicitys" do
171
+ subject.cardinality.must_equal(6)
172
+ end
173
+ end
174
+
175
+ describe "#size" do
176
+ it "should return the multiplicity of non-zero keys" do
177
+ subject.size.must_equal(2)
178
+ end
179
+ end
180
+
181
+ describe "#<=>" do
182
+ let(:small) { SignedMultiset[:foo, :bar] }
183
+ let(:large) { SignedMultiset[:foo, :bar, :baz, :foo, :bar, :qux, :foo, :bar] }
184
+ let(:equal) { subject.dup }
185
+
186
+ it "should return 1 when compared to a smaller set" do
187
+ (subject <=> small).must_equal(1)
188
+ end
189
+ it "should return -1 when compared to a larger set" do
190
+ (subject <=> large).must_equal(-1)
191
+ end
192
+ it "should return 0 when compared to an equal set" do
193
+ (subject <=> equal).must_equal(0)
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,4 @@
1
+ require 'signed_multiset'
2
+ require 'minitest/spec'
3
+ require 'minitest/autorun'
4
+ require 'minitest/pride'
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: signed_multiset
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Josh Lewis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-06-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Multisets with negative membership
56
+ email:
57
+ - josh.w.lewis@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - .ruby-version
64
+ - .travis.yml
65
+ - Gemfile
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - lib/signed_multiset.rb
70
+ - lib/signed_multiset/signed_multiset.rb
71
+ - lib/signed_multiset/version.rb
72
+ - signed_multiset.gemspec
73
+ - test/signed_multiset/signed_multiset_test.rb
74
+ - test/test_helper.rb
75
+ homepage: http://github.com/joshwlewis/signed_multiset
76
+ licenses:
77
+ - MIT
78
+ metadata: {}
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 2.0.2
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: Signed Multiset is a Ruby implementation of a Multiset that allows negative
99
+ membership. You can think of it as a Multiset or Bag that allows for negative counts.
100
+ It feels like a Ruby Hash or Array, but with some differences.
101
+ test_files:
102
+ - test/signed_multiset/signed_multiset_test.rb
103
+ - test/test_helper.rb
104
+ has_rdoc: