--- id: 5eb3e4b20aa93c437f9e9717 title: 実数集合 challengeType: 5 forumTopicId: 385322 dashedName: set-of-real-numbers --- # --description-- すべての実数は非可算集合 ℝ を形成します。 その部分集合のうち、比較的単純なものが凸集合です。それぞれが実数 *a* と *b* の区間として表されます (*a* ≤ *b*)。 実際には、「区間」の意味は境界の開・閉に応じて、4つのケースがあります。 *a* = *b* の場合、4つのうち \[*a*, *a*] のみが空集合になりません。 **タスク** # --instructions-- 2 つのオブジェクト、1 つの文字列、1 つの配列をパラメータとして取る関数を記述してください。 オブジェクトは集合を表し、次の属性を持ちます: `low`、`high` および `rangeType` `rangeType`では、`CLOSED`、`BOTH_OPEN`、`LEFT_OPEN`、`RIGHT_OPEN` に対して、それぞれ0、1、2、3の値を持つことができます。 この関数は、この情報を使用して集合を実装するものとします。 文字列は集合に実行される演算を表します。 以下のいずれかとなります。`"union"` (和集合)、`"intersect"` (共通部分、積集合)、`"subtract"` (差集合)。 演算の実行後、関数は配列内の値が結果の集合に存在するかどうかをチェックし、対応するブール値を配列に格納します。 この関数はこの配列を返す必要があります。 # --hints-- `realSet` は関数とします。 ```js assert(typeof realSet == 'function'); ``` `realSet({"low":0, "high":1, "rangeType":2}, {"low":0, "high":2, "rangeType":3}, "union", [1, 2, 3])` は配列を返す必要があります。 ```js assert( Array.isArray( realSet( { low: 0, high: 1, rangeType: 2 }, { low: 0, high: 2, rangeType: 3 }, 'union', [1, 2, 3] ) ) ); ``` `realSet({"low":0, "high":1, "rangeType":2}, {"low":0, "high":2, "rangeType":3}, "union", [1, 2, 3])` は `[true, false, false]` を返す必要があります。 ```js assert.deepEqual( realSet( { low: 0, high: 1, rangeType: 2 }, { low: 0, high: 2, rangeType: 3 }, 'union', [1, 2, 3] ), [true, false, false] ); ``` `realSet({"low":0, "high":2, "rangeType":3}, {"low":1, "high":2, "rangeType":2}, "intersect", [0, 1, 2])` は `[false, false, false]` を返す必要があります。 ```js assert.deepEqual( realSet( { low: 0, high: 2, rangeType: 3 }, { low: 1, high: 2, rangeType: 2 }, 'intersect', [0, 1, 2] ), [false, false, false] ); ``` `realSet({"low":0, "high":3, "rangeType":3}, {"low":0, "high":1, "rangeType":1}, "subtract", [0, 1, 2])` は `[true, true, true]` を返す必要があります。 ```js assert.deepEqual( realSet( { low: 0, high: 3, rangeType: 3 }, { low: 0, high: 1, rangeType: 1 }, 'subtract', [0, 1, 2] ), [true, true, true] ); ``` `realSet({"low":0, "high":3, "rangeType":3}, {"low":0, "high":1, "rangeType":0}, "subtract", [0, 1, 2])` は `[false, false, true]` を返す必要があります。 ```js assert.deepEqual( realSet( { low: 0, high: 3, rangeType: 3 }, { low: 0, high: 1, rangeType: 0 }, 'subtract', [0, 1, 2] ), [false, false, true] ); ``` `realSet({"low":0, "high":33, "rangeType":1}, {"low":30, "high":31, "rangeType":0}, "intersect", [30, 31, 32])` は `[true, true, false]` を返す必要があります。 ```js assert.deepEqual( realSet( { low: 0, high: 33, rangeType: 1 }, { low: 30, high: 31, rangeType: 0 }, 'intersect', [30, 31, 32] ), [true, true, false] ); ``` # --seed-- ## --seed-contents-- ```js function realSet(set1, set2, operation, values) { } ``` # --solutions-- ```js function realSet(set1, set2, operation, values) { const RangeType = { CLOSED: 0, BOTH_OPEN: 1, LEFT_OPEN: 2, RIGHT_OPEN: 3 }; function Predicate(test) { this.test = test; this.or = function(other) { return new Predicate(t => this.test(t) || other.test(t)); }; this.and = function(other) { return new Predicate(t => this.test(t) && other.test(t)); }; this.negate = function() { return new Predicate(t => !this.test(t)); }; } function RealSet(start, end, rangeType, predF) { this.low = start; this.high = end; if (predF) { this.predicate = new Predicate(predF); } else { this.predicate = new Predicate(d => { switch (rangeType) { case RangeType.CLOSED: return start <= d && d <= end; case RangeType.BOTH_OPEN: return start < d && d < end; case RangeType.LEFT_OPEN: return start < d && d <= end; case RangeType.RIGHT_OPEN: return start <= d && d < end; } }); } this.contains = function(d) { return this.predicate.test(d); }; this.union = function(other) { var low2 = Math.min(this.low, other.low); var high2 = Math.max(this.high, other.high); return new RealSet(low2, high2, null, d => this.predicate.or(other.predicate).test(d) ); }; this.intersect = function(other) { var low2 = Math.min(this.low, other.low); var high2 = Math.max(this.high, other.high); return new RealSet(low2, high2, null, d => this.predicate.and(other.predicate).test(d) ); }; this.subtract = function(other) { return new RealSet(this.low, this.high, null, d => this.predicate.and(other.predicate.negate()).test(d) ); }; } set1 = new RealSet(set1.low, set1.high, set1.rangeType); set2 = new RealSet(set2.low, set2.high, set2.rangeType); var result = []; values.forEach(function(value) { result.push(set1[operation](set2).contains(value)); }); return result; } ```