セット
表示
セット(Set; 集合)は、データ構造の一つで、重複を許さず、順序の概念がない要素の集まりを表します。集合は、数学の集合論に基づいて設計されたものであり、集合を操作するための様々な演算が定義されています。 集合には以下のような基本的な操作があります。
操作のインターフェース:
- Addition(要素の追加): 集合に新しい要素を追加します。
- Removal(要素の削除): 集合から指定した要素を削除します。
- Contains(要素が集合に属すか判定): 集合に指定した要素が含まれているかを判定します。x ∈ A
- Union(和集合): 2つの集合の要素を合わせて新しい集合を作ります。A ∪ B
- Intersection(積集合): 2つの集合に共通する要素を集めて新しい集合を作ります。A ∩ B
- Difference(差集合): 2つの集合のうち、1つ目の集合には含まれるが2つ目の集合には含まれない要素を集めて新しい集合を作ります。A \ B
- Subset(部分集合の判定): 1つの集合が別の集合の部分集合であるかどうかを判定します。A ⊆ B
実装例
[編集]Ruby
[編集]Rubyには、既に Set クラスがありますが、ここでは Array を継承して実装しました。
- RubyでSetを実装
# frozen_string_literal: true class MySet < Array def initialize(*args, &block) @head = nil case [args, block] in [], nil then return in [Array => ary], nil then ary.each { add _1 } in [Array => ary], block then ary.each { add block[_1] } in [Integer => size], nil if size >= 0 then size.times { add _1 } in [Integer => size], block if size >= 0 then size.times { add block[_1] } else raise ArgumentError, "#{self.class}#initialize: #{args.inspect} #{block && 'block_given!'}" end end # 要素の追加 def add(element) self << element unless contains?(element) end # 要素の削除 alias remove delete # 要素の検索 alias contains? include? # 集合の和 def union(other) = self.class.new(self + other) # 集合の積 def intersection(other) = self.class.new(self & other) # 集合の差 def difference(other) = self.class.new(self - other) # 部分集合の判定 def subset?(other) = other.size === 0 || all? { |element| other.contains?(element) } end require 'minitest/autorun' describe MySet do let(:set0) { MySet.new } let(:set12) { MySet.new [1, 2] } let(:set23) { MySet.new [2, 3] } describe '#initialize' do it 'initializes with no arguments' do expect(MySet.new).must_equal set0 end it 'initializes with an array argument' do # expect(MySet.new([1, 2, 3])).must_equal MySet.new(1, 2, 3) end it 'initializes with an array argument and block' do expect(MySet.new([4, 14, 6])).must_equal MySet.new([2, 7, 3]) { |x| 2 * x } end it 'initializes with a size argument' do expect(MySet.new([0, 1, 2])).must_equal MySet.new(3) end it 'initializes with a size argument and block' do expect(MySet.new([1, 3, 5])).must_equal MySet.new(3) { |x| 2 * x + 1} end it 'raises ArgumentError with invalid arguments' do expect { MySet.new('invalid') }.must_raise ArgumentError expect { MySet.new(-1) }.must_raise ArgumentError expect { MySet.new(1, 2, 3) { |x| x } }.must_raise ArgumentError end end describe '#add' do it 'adds an element to the set' do set0.add(1) expect(set0).must_equal MySet.new([1]) end it 'does not add an element already in the set' do set0.add(1) set0.add(1) expect(set0).must_equal MySet.new([1]) end end describe '#remove' do it 'removes an element from the set' do set0.add(1) set0.remove(1) expect(set0).must_equal MySet.new end end describe '#contains?' do it 'returns true if the set contains the element' do set0.add(1) expect(set0.contains?(1)).must_equal true end it 'returns false if the set does not contain the element' do expect(set0.contains?(1)).must_equal false end end describe '#union' do it 'returns the union of two sets' do expect(set12.union(set23)).must_equal MySet.new([1, 2, 3]) end end describe '#intersection' do it 'returns the intersection of two sets' do expect(set12.intersection(set23)).must_equal MySet.new([2]) end end describe '#difference' do it 'returns the difference of two sets' do expect(set12.difference(set23)).must_equal MySet.new([1]) end end describe '#subset?' do it 'returns true if the set is a subset of another set' do set12 = MySet.new([1, 2]) set123 = MySet.new([1, 2, 3]) expect(set12.subset?(set123)).must_equal true expect(set123.subset?(set12)).must_equal false end it 'returns false if the set is not a subset of another set' do expect(set12.subset?(set23)).must_equal false expect(set23.subset?(set12)).must_equal false end it 'returns true if the set is a subset of empty set' do expect(set12.subset?(set0)).must_equal true end it 'returns true if the set is a subset of set self' do expect(set12.subset?(set12)).must_equal true end end end