集合
メモというか。
内包とかJavaだと苦しいし、無限集合になるとマジどう扱うべきかわからん。
あと、コメントにも書いてあるけど、テストコードのリファクタリング、重複あるテストの削除とか整理とかって重要だと思うけど、その辺りの感覚がつかめない。書いたテストを全部残してりゃREDになる心配はないというか動作として問題がないことは確認できるんだろうけど、仕様を変更したいときとかインタフェースを変えたいときに当然テストコードも変更が必要になって、テストコードのどこまで影響するかよくわからなければ、必要な変更をしたくなくない方向になりそう。TDDの悩みどころ。
import org.junit.Test; import static org.junit.Assert.*; //TODO 内包的定義 //TODO 無限集合 //TODO 商集合 //TODO 全体集合 universe //TODO 空集合との直積はどうあるべき? //TODO 同値関係 // あれだ、テストケースもリファクタリングしてコンパクトに保たないと、仕様変更のときに負担になっちゃうわけだ。 public class FiniteSetTest { @Test public void 集合演算() { FiniteSet set1 = FiniteSet.valueOf("fuga", "hoge"); FiniteSet set2 = FiniteSet.valueOf("fuga", 1, 2); assertEquals(FiniteSet.valueOf("fuga", "hoge", 1, 2), set1.union(set2)); assertEquals(FiniteSet.valueOf("hoge"), set1.deff(set2)); assertEquals(FiniteSet.emptySet(), set1.deff(set1)); assertEquals(FiniteSet.valueOf("fuga"), set1.intersect(set2)); assertEquals(FiniteSet.valueOf( FiniteSet.valueOf("fuga", "hoge"), FiniteSet.valueOf(1, "hoge"), FiniteSet.valueOf("fuga", 2), FiniteSet.valueOf(1, 2) ), FiniteSet.valueOf("fuga", 1).card(FiniteSet.valueOf("hoge", 2)) ); } @Test public void 空集合() { assertTrue(FiniteSet.emptySet().isSubSetOf(FiniteSet.valueOf("hoge"))); assertTrue(FiniteSet.emptySet().isSubSetOf(FiniteSet.emptySet())); assertTrue(FiniteSet.emptySet().isSuperSetOf(FiniteSet.emptySet())); assertEquals(0, FiniteSet.emptySet().size()); assertEquals(FiniteSet.emptySet(), FiniteSet.valueOf()); } @Test public void 帰属と含有() { FiniteSet mySet = FiniteSet.valueOf("fuga", "hoge"); assertTrue(mySet.contains("fuga")); assertFalse(mySet.contains(1)); FiniteSet superSet = FiniteSet.valueOf("fuga", "hoge", 1); assertTrue(superSet.isSuperSetOf(mySet)); assertTrue(mySet.isSubSetOf(superSet)); FiniteSet mySet2 = FiniteSet.valueOf("fuga", "hoge"); assertEquals(mySet, mySet2); assertEquals(mySet.hashCode(), mySet2.hashCode()); } }
import java.util.*; public class FiniteSet { private static final FiniteSet phi = new FiniteSet(); public static FiniteSet valueOf(Object...elements) { if (elements.length == 0) return phi; return new FiniteSet(elements); } public static FiniteSet emptySet() { return phi; } private final Set<?> set; private FiniteSet(Object[] elements) { this.set = new HashSet<Object>(Arrays.asList(elements)); } private FiniteSet(Set<?>...sets) { HashSet<Object> s = new HashSet<Object>(); for (Set<?> set : sets) for (Object element : set) s.add(element); this.set = s; } public boolean contains(Object element) { return this.set.contains(element); } public boolean isSuperSetOf(FiniteSet subSet) { return this.set.containsAll(subSet.set); } public boolean isSubSetOf(FiniteSet superSet) { return superSet.set.containsAll(this.set); } public FiniteSet union(FiniteSet that) { return new FiniteSet(this.set, that.set); } @Override public boolean equals(Object arg0) { if (arg0 instanceof FiniteSet) return this.set.equals(((FiniteSet) arg0).set); return false; } @Override public int hashCode() { return this.set.hashCode(); } @Override public String toString() { return this.set.toString(); } public int size() { return this.set.size(); } public FiniteSet deff(FiniteSet that) { Set<Object> s = new HashSet<Object>(); s.addAll(this.set); s.removeAll(that.set); return new FiniteSet(s); } public FiniteSet intersect(FiniteSet that) { Set<Object> s = new HashSet<Object>(); s.addAll(this.set); s.retainAll(that.set); return new FiniteSet(s); } public FiniteSet card(FiniteSet that) { Set<Object> s = new HashSet<Object>(); for (Object e1 : this.set) { for (Object e2 : that.set) { s.add(FiniteSet.valueOf(e1, e2)); } } return new FiniteSet(s); } }