multiset 0.3.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.
@@ -0,0 +1,757 @@
1
+ #==概要(Basic information)
2
+ #
3
+ #Rubyによる多重集合(マルチセット)の実装です。
4
+ #通常の集合(Rubyでは"set"ライブラリ)と異なり、多重集合は
5
+ #同一の要素を複数格納することができます。
6
+ #
7
+ #メソッド名は基本的にSetクラスに合わせてあります。またSetクラスが持つ
8
+ #メソッドの大部分を実装していますが、いくつか未実装なものもあります。
9
+ #
10
+ #Ruby implementation of multiset.
11
+ #Unlike ordinary set(see Ruby documentation for "set" library),
12
+ #multiset can contain two or more same items.
13
+ #
14
+ #Most methods' names are same as those of Set class, and all other than
15
+ #a few methods in Set class is implemented on Multiset class.
16
+ #
17
+ #* <code>Set[:a,:b,:c,:b,:b,:c] => #<Set: {:b, :c, :a}></code>
18
+ #* <code>Multiset[:a,:b,:c,:b,:b,:c] => #<Multiset:<tt>#</tt>3 :b, <tt>#</tt>2 :c, <tt>#</tt>1 :a></code>
19
+
20
+ class Multiset
21
+ include Enumerable
22
+ @@parse_string = true
23
+
24
+ #--
25
+ # Constructors
26
+ #++
27
+
28
+ # <code>list</code>に含まれる要素からなる多重集合を生成します。
29
+ # <code>list</code>を省略した場合、空の多重集合を生成します。
30
+ #
31
+ # <code>list</code>には<code>Enumerable</code>であるオブジェクトのみ
32
+ # 指定できます。そうでない場合、例外<code>ArgumentError</code>が
33
+ # 発生します。
34
+ #
35
+ # Generates a multiset from items in <code>list</code>.
36
+ # If <code>list</code> is omitted, returns empty multiset.
37
+ #
38
+ # <code>list</code> must be <code>Enumerable</code>. If not,
39
+ # <code>ArgumentError</code> is raised.
40
+ def initialize(list = nil)
41
+ @items = {}
42
+ if list.kind_of?(Enumerable)
43
+ list.each{ |item| add item }
44
+ elsif list != nil
45
+ raise ArgumentError, "Item list must include 'Enumerable' module"
46
+ end
47
+ end
48
+
49
+ # <code>list</code>に含まれる要素からなる多重集合を生成します。
50
+ # <code>new</code>を用いる場合と異なり、引数の1つ1つが多重集合の要素になります。
51
+ #
52
+ # 主に多重集合のリテラルを生成するのに用います。
53
+ #
54
+ # Generates a multiset from items in <code>list</code>.
55
+ # Unlike using <code>new</code>, each argument is one item in generated multiset.
56
+ #
57
+ # This method is mainly used when you generate literal of multiset.
58
+ def Multiset.[](*list)
59
+ Multiset.new(list)
60
+ end
61
+
62
+ # <code>object</code>を多重集合に変換し生成します。
63
+ # * <code>object</code>がMultisetのインスタンスである場合、
64
+ # その複製を返します。
65
+ # * <code>object</code>がMultisetのインスタンスでなく、
66
+ # かつ<code>each_pair</code>メソッドを持っている場合、
67
+ # <code>each_pair</code>から渡される2つの引数について、前者を要素、
68
+ # 後者をその個数とした多重集合を生成します。Hash#to_multisetも
69
+ # ご覧下さい。
70
+ # * <code>object</code>が<code>each_pair</code>メソッドを持っておらず、
71
+ # かつ<code>Enumerable</code>である場合は、Multiset#newと同じ結果です。
72
+ # * それ以外の場合は、例外<code>ArgumentError</code>が発生します。
73
+ #
74
+ # Generates a multiset converting <code>object</code>.
75
+ # * If <code>object</code> is an instance of Multiset, returns
76
+ # duplicated <code>object</code>.
77
+ # * If <code>object</code> is not an instance of Multiset and has
78
+ # the method <code>each_pair</code>,
79
+ # for each pair of two arguments from <code>each_pair</code>,
80
+ # first argument becomes item in multiset and second argument
81
+ # becomes its number. See also Hash#to_multiset .
82
+ # * If <code>object</code> does not have the method <code>each_pair</code>
83
+ # and <code>object</code> includes <code>Enumerable</code>, this method
84
+ # results equal to Multiset#new .
85
+ # * Otherwise, <code>ArgumentError</code> is raised.
86
+ def Multiset.parse(object)
87
+ if !@@parse_string && object.kind_of?(String)
88
+ raise ArgumentError, "Multiset.parse can not parse strings"
89
+ end
90
+ Multiset.parse_force(object)
91
+ end
92
+
93
+ # Multiset.parseと同様ですが、挙動がMultiset.parse_stringの設定に
94
+ # 影響されません(<code>Multiset.parse_string(true)</code>の場合と
95
+ # 同様とみなします)。
96
+ #
97
+ # Same as Multiset.parse, but this method is not affected
98
+ # by the setting of Multiset.parse_string (treats
99
+ # <code>Multiset.parse_string(true)</code>) .
100
+ def Multiset.parse_force(object)
101
+ if object.instance_of?(Multiset)
102
+ ret = object.dup
103
+ else
104
+ ret = Multiset.new
105
+ if defined? object.each_pair
106
+ object.each_pair{ |item, count| ret.add item, count }
107
+ elsif object.kind_of?(Enumerable)
108
+ object.each{ |item| ret.add item }
109
+ else
110
+ raise ArgumentError, "Source of Multiset must have 'each_pair' method or include 'Enumerable' module"
111
+ end
112
+ end
113
+ ret
114
+ end
115
+
116
+ # Multiset.parseの引数にStringを渡すことを許すか指定します。
117
+ #
118
+ # StringはEnumerableなので、Multiset.parseでは引数として文字列を
119
+ # 渡すこともできます。しかしこれはバグの危険性があるため、
120
+ # このメソッドで禁止することができます。
121
+ #
122
+ # <code>boolean</code>にはtrueおよびfalseが指定できます。
123
+ # falseを設定した場合、Multiset.parseやMultimap#[]=などで
124
+ # 文字列を直接指定した場合に<code>ArgumentError</code>が発生します。
125
+ # デフォルト値は<code>true</code>です。
126
+ #
127
+ # <code>boolean</code>を省略した場合は、現在のこの値がtrueか
128
+ # falseかを返します。
129
+ #
130
+ # この値はクラス変数で管理されているので、一度変更するとすべての
131
+ # インスタンスに影響が及びます。
132
+ #
133
+ # Allows or prohibits Strings from being arguments of Multiset.parse .
134
+ #
135
+ # String includes module Enumerable, therefore you can give a string as
136
+ # an argument of Multiset.parse . But this may cause bugs,
137
+ # so you can prohibit this.
138
+ #
139
+ # <code>boolean</code> can be true or false. If this value is false,
140
+ # <code>ArgumentError</code> is raised whenever you specify a string
141
+ # as an argument of Multiset.parse , Multimap#[]= , and so on.
142
+ # This value is <code>true</code> by default.
143
+ #
144
+ # If <code>boolean</code> is not specified, returns current value
145
+ # (true or false).
146
+ #
147
+ # This value is stored in class variable, therefore this value has
148
+ # effect for all instances of Multiset.
149
+ def Multiset.parse_string(boolean = nil)
150
+ case boolean
151
+ when true, false
152
+ @@parse_string = boolean
153
+ when nil
154
+ else
155
+ raise ArgumentError, "Argument must be true or false"
156
+ end
157
+ @@parse_string
158
+ end
159
+
160
+ # Same as Multiset.parse_string
161
+ def Multiset.parse_string?(boolean = nil)
162
+ Multiset.parse_string boolean
163
+ end
164
+
165
+ # <code>self</code>の複製を生成して返します。
166
+ #
167
+ # Returns duplicated <code>self</code>.
168
+ def dup
169
+ @items.to_multiset
170
+ end
171
+
172
+ # <code>self</code>を<code>Hash</code>に変換して返します。
173
+ # 生成されるハッシュの構造については、Hash#to_multisetをご覧下さい。
174
+ #
175
+ # Converts <code>self</code> to a <code>Hash</code>.
176
+ # See Hash#to_multiset about format of generated hash.
177
+ def to_hash
178
+ @items.dup
179
+ end
180
+
181
+ # <code>self</code>を通常の集合(Ruby標準添付の<code>Set</code>)に
182
+ # 変換したものを返します。
183
+ #
184
+ # このメソッドを呼び出すと、<code>require "set"</code>が行われます。
185
+ #
186
+ # なおSetをMultisetに変換するには、<code>Multiset.new(instance_of_set)</code>で
187
+ # 可能です。
188
+ #
189
+ # Converts <code>self</code> to ordinary set
190
+ # (The <code>Set</code> class attached to Ruby by default).
191
+ #
192
+ # <code>require "set"</code> is performed when this method is called.
193
+ #
194
+ # To convert Set to Multiset, use <code>Multiset.new(instance_of_set)</code>.
195
+ def to_set
196
+ require "set"
197
+ Set.new(@items.keys)
198
+ end
199
+
200
+ # <code>self</code>を配列に変換して返します。
201
+ #
202
+ # Converts <code>self</code> to an array.
203
+ def to_a
204
+ ret = []
205
+ @items.each_pair do |item, count|
206
+ ret.concat Array.new(count, item)
207
+ end
208
+ ret
209
+ end
210
+
211
+ def hash # :nodoc:
212
+ val = 0
213
+ @items.each_pair do |item, count|
214
+ val += item.hash * count
215
+ end
216
+ val
217
+ end
218
+
219
+ def eql?(other) # :nodoc:
220
+ if self.hash == other.hash
221
+ self == other
222
+ else
223
+ false
224
+ end
225
+ end
226
+
227
+ # <code>self</code>の内容を<code>other</code>のものに置き換えます。
228
+ # <code>self</code>を返します。
229
+ #
230
+ # Replaces <code>self</code> by <code>other</code>.
231
+ # Returns <code>self</code>.
232
+ def replace(other)
233
+ @items.clear
234
+ other.each_pair do |item, count|
235
+ self.renew_count(item, count)
236
+ end
237
+ self
238
+ end
239
+
240
+ # <code>self</code>に含まれている要素数を返します。
241
+ #
242
+ # Returns number of all items in <code>self</code>.
243
+ def size
244
+ @items.inject(0){ |sum, item| sum += item[1] }
245
+ end
246
+ alias length size
247
+
248
+ # <code>self</code>に要素がないかどうかを返します。
249
+ #
250
+ # Returns whether <code>self</code> has no item.
251
+ def empty?
252
+ @items.empty?
253
+ end
254
+
255
+ # <code>self</code>に含まれている要素(重複は除く)からなる配列を返します。
256
+ #
257
+ # Returns an array with all items in <code>self</code>, without duplication.
258
+ def items
259
+ @items.keys
260
+ end
261
+
262
+ # <code>self</code>の要素をすべて削除します。
263
+ # <code>self</code>を返します。
264
+ #
265
+ # Deletes all items in <code>self</code>.
266
+ # Returns <code>self</code>.
267
+ def clear
268
+ @items.clear
269
+ self
270
+ end
271
+
272
+ # <code>item</code>が<code>self</code>中に含まれているかを返します。
273
+ #
274
+ # Returns whether <code>self</code> has <code>item</code>.
275
+ def include?(item)
276
+ @items.has_key?(item)
277
+ end
278
+ alias member? include?
279
+
280
+ # <code>self</code>中に含まれる<code>item</code>の個数を返します。
281
+ #
282
+ # Returns number of <code>item</code>s in <code>self</code>.
283
+ def count(item)
284
+ @items.has_key?(item) ? @items[item] : 0
285
+ end
286
+
287
+ # <code>self</code>に含まれるすべての要素について繰り返します。
288
+ # <code>self</code>を返します。
289
+ #
290
+ # Iterates for each item in <code>self</code>.
291
+ # Returns <code>self</code>.
292
+ def each
293
+ @items.each_pair do |item, count|
294
+ count.times{ yield item }
295
+ end
296
+ self
297
+ end
298
+
299
+ # <code>self</code>に含まれるすべての要素について、重複を許さずに繰り返します。
300
+ # <code>self</code>を返します。
301
+ #
302
+ # Iterates for each item in <code>self</code>, without duplication.
303
+ # Returns <code>self</code>.
304
+ def each_item(&block) # :yields: item
305
+ @items.each_key(&block)
306
+ self
307
+ end
308
+
309
+ # <code>self</code>に含まれるすべての要素とその個数について繰り返します。
310
+ # <code>self</code>を返します。
311
+ #
312
+ # Iterates for each pair of item and its number in <code>self</code>.
313
+ # Returns <code>self</code>.
314
+ def each_pair(&block) # :yields: item, count
315
+ @items.each_pair(&block)
316
+ self
317
+ end
318
+
319
+ # <code>self</code>に含まれる<code>item</code>の個数を<code>number</code>個にします。
320
+ # <code>number</code>が負の数であった場合は、<code>number = 0</code>とみなします。
321
+ # 成功した場合は<code>self</code>を、失敗した場合は<code>nil</code>を返します。
322
+ #
323
+ # Sets number of <code>item</code> to <code>number</code> in <code>self</code>.
324
+ # If <code>number</code> is negative, treats as <code>number = 0</code>.
325
+ # Returns <code>self</code> if succeeded, <code>nil</code> otherwise.
326
+ def renew_count(item, number)
327
+ return nil if number == nil
328
+ n = number.to_i
329
+ if n > 0
330
+ @items[item] = n
331
+ else
332
+ @items.delete(item)
333
+ end
334
+ self
335
+ end
336
+
337
+ # <code>self</code>の各要素をブロックに与え、返り値を集めたものからなる
338
+ # 多重集合を生成します。
339
+ #
340
+ # Gives all items in <code>self</code> to given block,
341
+ # and generates a new multiset whose values are returned value from the block.
342
+ def map
343
+ ret = Multiset.new
344
+ self.each do |item|
345
+ ret << yield(item)
346
+ end
347
+ ret
348
+ end
349
+ alias collect map
350
+
351
+ # Multiset#mapと同様ですが、結果として生成される多重集合で<code>self</code>が
352
+ # 置き換えられます。<code>self</code>を返します。
353
+ #
354
+ # Same as Multiset#map, but replaces <code>self</code> by resulting multiset.
355
+ # Returns <code>self</code>.
356
+ def map!
357
+ self.to_a.each do |item|
358
+ self.delete(item)
359
+ self << yield(item)
360
+ end
361
+ self
362
+ end
363
+ alias collect! map!
364
+
365
+ # <code>self</code>の要素とその個数の組をブロックに与えます。
366
+ # ブロックから2要素の配列を受け取り、前者を要素、後者をその個数とした
367
+ # 多重集合を生成します。
368
+ #
369
+ # Gives all pairs of items and their numbers in <code>self</code> to
370
+ # given block. The block must return an array of two items.
371
+ # Generates a new multiset whose values and numbers are the first and
372
+ # second item of returned array, respectively.
373
+ def map_with
374
+ ret = Multiset.new
375
+ self.each_pair do |item, count|
376
+ val = yield(item, count)
377
+ ret.add(val[0], val[1])
378
+ end
379
+ ret
380
+ end
381
+ alias collect_with map_with
382
+
383
+ # Multiset#map_withと同様ですが、結果として生成される多重集合で
384
+ # <code>self</code>が置き換えられます。<code>self</code>を返します。
385
+ #
386
+ # Same as Multiset#map_with, but replaces <code>self</code> by
387
+ # resulting multiset. Returns <code>self</code>.
388
+ def map_with!
389
+ self.to_hash.each_pair do |item, count|
390
+ self.delete(item, count)
391
+ val = yield(item, count)
392
+ self.add(val[0], val[1])
393
+ end
394
+ self
395
+ end
396
+ alias collect_with! map_with!
397
+
398
+ # <code>self</code>の要素を無作為に1つ選んで返します。
399
+ # すべての要素は等確率で選ばれます。
400
+ #
401
+ # Returns one item in <code>self</code> randomly.
402
+ # All items are selected with same probability.
403
+ def rand
404
+ pos = Kernel.rand(self.size)
405
+ @items.each_pair do |item, count|
406
+ pos -= count
407
+ return item if pos < 0
408
+ end
409
+ end
410
+
411
+ # <code>self</code>と<code>other</code>が持つすべての要素(重複なし)について
412
+ # 繰り返し、ブロックの返り値が偽であるものが存在すればその時点でfalseを返します。
413
+ # すべての要素について真であればtrueを返します。
414
+ #
415
+ # このメソッドはsuperset?、subset?、== のために定義されています。
416
+ #
417
+ # Iterates for each item in <code>self</code> and <code>other</code>,
418
+ # without duplication. If the given block returns false, then iteration
419
+ # immediately ends and returns false.
420
+ # Returns true if the given block returns true for all of iteration.
421
+ #
422
+ # This method is defined for methods superset?, subset?, ==.
423
+ def compare_set_with(other) # :nodoc: :yields: number_in_self, number_in_other
424
+ check = self.items.dup
425
+ check.concat(other.items)
426
+ check.each do |item|
427
+ return false unless yield(self.count(item), other.count(item))
428
+ end
429
+ true
430
+ end
431
+
432
+ # <code>self</code>が<code>other</code>を含んでいるかどうかを返します。
433
+ #
434
+ # Returns whether <code>self</code> is a superset of <code>other</code>.
435
+ def superset?(other)
436
+ unless other.instance_of?(Multiset)
437
+ raise ArgumentError, "Argument must be a Multiset"
438
+ end
439
+ compare_set_with(other){ |s, o| s >= o }
440
+ end
441
+
442
+ # <code>self</code>が<code>other</code>を真に含んでいるかどうかを返します。
443
+ # 「真に」とは、両者が一致する場合は含めないことを示します。
444
+ #
445
+ # Returns whether <code>self</code> is a proper superset of <code>other</code>.
446
+ def proper_superset?(other)
447
+ unless other.instance_of?(Multiset)
448
+ raise ArgumentError, "Argument must be a Multiset"
449
+ end
450
+ self.superset?(other) && self != other
451
+ end
452
+
453
+ # <code>self</code>が<code>other</code>に含まれているかどうかを返します。
454
+ #
455
+ # Returns whether <code>self</code> is a subset of <code>other</code>.
456
+ def subset?(other)
457
+ unless other.instance_of?(Multiset)
458
+ raise ArgumentError, "Argument must be a Multiset"
459
+ end
460
+ compare_set_with(other){ |s, o| s <= o }
461
+ end
462
+
463
+ # <code>self</code>が<code>other</code>に真に含まれているかどうかを返します。
464
+ # 「真に」とは、両者が一致する場合は含めないことを示します。
465
+ #
466
+ # Returns whether <code>self</code> is a proper subset of <code>other</code>.
467
+ def proper_subset?(other)
468
+ unless other.instance_of?(Multiset)
469
+ raise ArgumentError, "Argument must be a Multiset"
470
+ end
471
+ self.subset?(other) && self != other
472
+ end
473
+
474
+ # <code>self</code>が<code>other</code>と等しいかどうかを返します。
475
+ #
476
+ # Returns whether <code>self</code> is equal to <code>other</code>.
477
+ def ==(other)
478
+ return false unless other.instance_of?(Multiset)
479
+ compare_set_with(other){ |s, o| s == o }
480
+ end
481
+
482
+ # <code>self</code>中に含まれる多重集合を平滑化したものを返します。
483
+ #
484
+ # Generates a multiset such that multisets in <code>self</code> are flattened.
485
+ def flatten
486
+ ret = Multiset.new
487
+ self.each do |item|
488
+ if item.kind_of?(Multiset)
489
+ ret += item.flatten
490
+ else
491
+ ret << item
492
+ end
493
+ end
494
+ ret
495
+ end
496
+
497
+ # <code>self</code>中に含まれる多重集合を平滑化します。
498
+ # 平滑化した多重集合が1つでもあれば<code>self</code>を、
499
+ # そうでなければ<code>nil</code>を返します。
500
+ #
501
+ # Flattens multisets in <code>self</code>.
502
+ # Returns <code>self</code> if any item is flattened,
503
+ # <code>nil</code> otherwise.
504
+ def flatten!
505
+ ret = nil
506
+ self.to_a.each do |item|
507
+ if item.kind_of?(Multiset)
508
+ self.delete(item)
509
+ self.merge!(item.flatten)
510
+ ret = self
511
+ end
512
+ end
513
+ ret
514
+ end
515
+
516
+ # <code>self</code>に、<code>addcount</code>個の<code>item</code>を追加します。
517
+ # 成功した場合は<code>self</code>を、失敗した場合は<code>nil</code>を返します。
518
+ #
519
+ # Adds <code>addcount</code> number of <code>item</code>s to <code>self</code>.
520
+ # Returns <code>self</code> if succeeded, or <code>nil</code> if failed.
521
+ def add(item, addcount = 1)
522
+ return nil if addcount == nil
523
+ a = addcount.to_i
524
+ return nil if a <= 0
525
+ self.renew_count(item, self.count(item) + a)
526
+ end
527
+ alias << add
528
+
529
+ # <code>self</code>から、<code>delcount</code>個の<code>item</code>を削除します。
530
+ # 成功した場合は<code>self</code>を、失敗した場合は<code>nil</code>を返します。
531
+ #
532
+ # Deletes <code>delcount</code> number of <code>item</code>s
533
+ # from <code>self</code>.
534
+ # Returns <code>self</code> if succeeded, <code>nil</code> otherwise.
535
+ def delete(item, delcount = 1)
536
+ return nil if delcount == nil || !self.include?(item)
537
+ d = delcount.to_i
538
+ return nil if d <= 0
539
+ self.renew_count(item, self.count(item) - d)
540
+ end
541
+
542
+ # <code>self</code>に含まれる<code>item</code>をすべて削除します。
543
+ # <code>self</code>を返します。
544
+ #
545
+ # Deletes all <code>item</code>s in <code>self</code>.
546
+ # Returns <code>self</code>.
547
+ def delete_all(item)
548
+ @items.delete(item)
549
+ self
550
+ end
551
+
552
+ # delete_ifと同じですが、要素が1つも削除されなければ<code>nil</code>を返します。
553
+ #
554
+ # Same as delete_if, but returns <code>nil</code> if no item is deleted.
555
+ def reject!
556
+ ret = nil
557
+ self.to_a.each do |item|
558
+ if yield(item)
559
+ ret = self if self.delete(item) == self
560
+ end
561
+ end
562
+ ret
563
+ end
564
+
565
+ # ブロックに<code>self</code>の要素を順次与え、
566
+ # 結果が真であった要素をすべて削除します。
567
+ # <code>self</code>を返します。
568
+ #
569
+ # Gives all items in <code>self</code> to given block,
570
+ # and deletes that item if the block returns true.
571
+ # Returns <code>self</code>.
572
+ def delete_if
573
+ self.to_a.each do |item|
574
+ @items.delete(item) if yield(item)
575
+ end
576
+ self
577
+ end
578
+
579
+ # <code>self</code>に含まれるすべての要素とその個数について、
580
+ # その組をブロックに与え、結果が真であった要素をすべて削除します。
581
+ # <code>self</code>を返します。
582
+ #
583
+ # Gives each pair of item and its number to given block,
584
+ # and deletes those items if the block returns true.
585
+ # Returns <code>self</code>.
586
+ def delete_with
587
+ @items.each_pair do |item, count|
588
+ @items.delete(item) if yield(item, count)
589
+ end
590
+ self
591
+ end
592
+
593
+ # <code>self</code>と<code>other</code>の要素を合わせた多重集合を返します。
594
+ #
595
+ # Returns merged multiset of <code>self</code> and <code>other</code>.
596
+ def merge(other)
597
+ ret = self.dup
598
+ other.each_pair do |item, count|
599
+ ret.add(item, count)
600
+ end
601
+ ret
602
+ end
603
+ alias + merge
604
+
605
+ # <code>self</code>に<code>other</code>の要素を追加します。
606
+ # <code>self</code>を返します。
607
+ #
608
+ # Merges <code>other</code> to <code>self</code>.
609
+ # Returns <code>self</code>.
610
+ def merge!(other)
611
+ other.each_pair do |item, count|
612
+ self.add(item, count)
613
+ end
614
+ self
615
+ end
616
+
617
+ # <code>self</code>から<code>other</code>の要素を取り除いた多重集合を返します。
618
+ #
619
+ # Returns multiset such that items in <code>other</code> are removed from <code>self</code>.
620
+ def subtract(other)
621
+ ret = self.dup
622
+ other.each_pair do |item, count|
623
+ ret.delete(item, count)
624
+ end
625
+ ret
626
+ end
627
+ alias - subtract
628
+
629
+ # <code>self</code>から<code>other</code>の要素を削除します。
630
+ # <code>self</code>を返します。
631
+ #
632
+ # Removes items in <code>other</code> from <code>self</code>.
633
+ # Returns <code>self</code>.
634
+ def subtract!(other)
635
+ other.each_pair do |item, count|
636
+ self.delete(item, count)
637
+ end
638
+ self
639
+ end
640
+
641
+ # <code>self</code>と<code>other</code>の積集合からなる多重集合を返します。
642
+ #
643
+ # Returns intersection of <code>self</code> and <code>other</code>.
644
+ def &(other)
645
+ ret = Multiset.new
646
+ (self.items & other.items).each do |item|
647
+ ret.renew_count(item, [self.count(item), other.count(item)].min)
648
+ end
649
+ ret
650
+ end
651
+
652
+ # <code>self</code>と<code>other</code>の和集合からなる多重集合を返します。
653
+ #
654
+ # Returns union of <code>self</code> and <code>other</code>.
655
+ def |(other)
656
+ ret = self.dup
657
+ other.each_pair do |item, count|
658
+ ret.renew_count(item, [self.count(item), count].max)
659
+ end
660
+ ret
661
+ end
662
+
663
+ # <code>self</code>の要素を、与えられたブロックからの返り値によって分類します。
664
+ # ブロックからの返り値をキーとして値を対応付けたMultimapを返します。
665
+ #
666
+ # Classify items in <code>self</code> by returned value from block.
667
+ # Returns a Multimap whose values are associated with keys. Keys'
668
+ # are defined by returned value from given block.
669
+ def classify
670
+ ret = Multimap.new
671
+ self.each do |item|
672
+ ret[yield(item)].add(item)
673
+ end
674
+ ret
675
+ end
676
+
677
+ # classifyと同様ですが、ブロックには要素とその個数の組が与えられます。
678
+ #
679
+ # Same as classify, but the pair of item and its number is given to block.
680
+ def classify_with
681
+ ret = Multimap.new
682
+ self.each_pair do |item, count|
683
+ ret[yield(item, count)].add(item, count)
684
+ end
685
+ ret
686
+ end
687
+
688
+ # <code>self</code>の全要素を(重複を許して)並べた文字列を返します。
689
+ # 要素間の区切りは<code>delim</code>の値を用い、
690
+ # 各要素の表示形式は与えられたブロックの返り値(なければObject#inspect)を用います。
691
+ #
692
+ # Lists all items with duplication in <code>self</code>.
693
+ # Items are deliminated with <code>delim</code>, and items are
694
+ # converted to string in the given block.
695
+ # If block is omitted, Object#inspect is used.
696
+ def listing(delim = "\n")
697
+ buf = ''
698
+ init = true
699
+ self.each do |item|
700
+ if init
701
+ init = false
702
+ else
703
+ buf += delim
704
+ end
705
+ buf += block_given? ? yield(item).to_s : item.inspect
706
+ end
707
+ buf
708
+ end
709
+
710
+ # <code>self</code>の要素と要素数の組を並べた文字列を返します。
711
+ # 要素間の区切りは<code>delim</code>の値を用い、
712
+ # 各要素の表示形式は与えられたブロックの返り値(なければObject#inspect)を用います。
713
+ #
714
+ # Lists all items without duplication and its number in <code>self</code>.
715
+ # Items are deliminated with <code>delim</code>, and items are
716
+ # converted to string in the given block.
717
+ # If block is omitted, Object#inspect is used.
718
+ def to_s(delim = "\n")
719
+ buf = ''
720
+ init = true
721
+ self.each_pair do |item, count|
722
+ if init
723
+ init = false
724
+ else
725
+ buf += delim
726
+ end
727
+ item_tmp = block_given? ? yield(item) : item.inspect
728
+ buf += "\##{count} #{item_tmp}"
729
+ end
730
+ buf
731
+ end
732
+
733
+ def inspect # :nodoc:
734
+ buf = "#<Multiset:"
735
+ buf += self.to_s(', ')
736
+ buf += '>'
737
+ buf
738
+ end
739
+ end
740
+
741
+ class Hash
742
+ # <code>self</code>を多重集合に変換し、その結果を返します。
743
+ # キーを要素、キーに対応する値をその要素の要素数とします。
744
+ #
745
+ # (例)<code>{:a => 4, :b => 2}.to_multiset # :aを4個、:bを2個含む多重集合</code>
746
+ #
747
+ # Generates multiset from <code>self</code>.
748
+ # Keys are treated as elements, and values are number of elements
749
+ # in the multiset. For example,
750
+ #
751
+ # <code>{:a => 4, :b => 2}.to_multiset # Multiset with four :a's and two :b's</code>
752
+ def to_multiset
753
+ ret = Multiset.new
754
+ self.each_pair{ |item, count| ret.renew_count(item, count) }
755
+ ret
756
+ end
757
+ end