multiset 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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