Set of real numbers: Difference between revisions

Added FreeBASIC
(J: removed defn of (in) - not using it)
(Added FreeBASIC)
 
(48 intermediate revisions by 21 users not shown)
Line 25:
 
'''Implementation notes'''
* 'Any' real set means 'sets that can be expressed as the union of a finite number of convex real sets'. Cantor's set needsneed not apply.
* Infinities should be handled gracefully; indeterminate numbers (NaN) can be ignored.
* You can use your machine's native real number representation, which is probably IEEE floating point, and assume it's good enough (it usually is).
Line 33:
* Define ''[http://www.wolframalpha.com/input/?i=%7Csin%28pi+x2%29%7C%3E1%2F2%2C+0+%3C+x+%3C+10 A]'' = {''x'' | 0 < ''x'' < 10 and |sin(π ''x''²)| > 1/2 }, ''[http://www.wolframalpha.com/input/?i=%7Csin%28pi+x%29%7C%3E1%2F2%2C+0+%3C+x+%3C+10 B]'' = {''x'' | 0 < ''x'' < 10 and |sin(π ''x'')| > 1/2}, calculate the length of the real axis covered by the set ''A'' − ''B''. Note that
|sin(π ''x'')| > 1/2 is the same as ''n'' + 1/6 < ''x'' < ''n'' + 5/6 for all integers ''n''; your program does not need to derive this by itself.
 
=={{header|C}}==
Providing an implementation of lambdas would be better, but this should do for now.
<syntaxhighlight lang="c">#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
 
struct RealSet {
bool(*contains)(struct RealSet*, struct RealSet*, double);
struct RealSet *left;
struct RealSet *right;
double low, high;
};
 
typedef enum {
CLOSED,
LEFT_OPEN,
RIGHT_OPEN,
BOTH_OPEN,
} RangeType;
 
double length(struct RealSet *self) {
const double interval = 0.00001;
double p = self->low;
int count = 0;
 
if (isinf(self->low) || isinf(self->high)) return -1.0;
if (self->high <= self->low) return 0.0;
 
do {
if (self->contains(self, NULL, p)) count++;
p += interval;
} while (p < self->high);
return count * interval;
}
 
bool empty(struct RealSet *self) {
if (self->low == self->high) {
return !self->contains(self, NULL, self->low);
}
return length(self) == 0.0;
}
 
static bool contains_closed(struct RealSet *self, struct RealSet *_, double d) {
return self->low <= d && d <= self->high;
}
 
static bool contains_left_open(struct RealSet *self, struct RealSet *_, double d) {
return self->low < d && d <= self->high;
}
 
static bool contains_right_open(struct RealSet *self, struct RealSet *_, double d) {
return self->low <= d && d < self->high;
}
 
static bool contains_both_open(struct RealSet *self, struct RealSet *_, double d) {
return self->low < d && d < self->high;
}
 
static bool contains_intersect(struct RealSet *self, struct RealSet *_, double d) {
return self->left->contains(self->left, NULL, d) && self->right->contains(self->right, NULL, d);
}
 
static bool contains_union(struct RealSet *self, struct RealSet *_, double d) {
return self->left->contains(self->left, NULL, d) || self->right->contains(self->right, NULL, d);
}
 
static bool contains_subtract(struct RealSet *self, struct RealSet *_, double d) {
return self->left->contains(self->left, NULL, d) && !self->right->contains(self->right, NULL, d);
}
 
struct RealSet* makeSet(double low, double high, RangeType type) {
bool(*contains)(struct RealSet*, struct RealSet*, double);
struct RealSet *rs;
 
switch (type) {
case CLOSED:
contains = contains_closed;
break;
case LEFT_OPEN:
contains = contains_left_open;
break;
case RIGHT_OPEN:
contains = contains_right_open;
break;
case BOTH_OPEN:
contains = contains_both_open;
break;
default:
return NULL;
}
 
rs = malloc(sizeof(struct RealSet));
rs->contains = contains;
rs->left = NULL;
rs->right = NULL;
rs->low = low;
rs->high = high;
return rs;
}
 
struct RealSet* makeIntersect(struct RealSet *left, struct RealSet *right) {
struct RealSet *rs = malloc(sizeof(struct RealSet));
rs->contains = contains_intersect;
rs->left = left;
rs->right = right;
rs->low = fmin(left->low, right->low);
rs->high = fmin(left->high, right->high);
return rs;
}
 
struct RealSet* makeUnion(struct RealSet *left, struct RealSet *right) {
struct RealSet *rs = malloc(sizeof(struct RealSet));
rs->contains = contains_union;
rs->left = left;
rs->right = right;
rs->low = fmin(left->low, right->low);
rs->high = fmin(left->high, right->high);
return rs;
}
 
struct RealSet* makeSubtract(struct RealSet *left, struct RealSet *right) {
struct RealSet *rs = malloc(sizeof(struct RealSet));
rs->contains = contains_subtract;
rs->left = left;
rs->right = right;
rs->low = left->low;
rs->high = left->high;
return rs;
}
 
int main() {
struct RealSet *a = makeSet(0.0, 1.0, LEFT_OPEN);
struct RealSet *b = makeSet(0.0, 2.0, RIGHT_OPEN);
struct RealSet *c = makeSet(1.0, 2.0, LEFT_OPEN);
struct RealSet *d = makeSet(0.0, 3.0, RIGHT_OPEN);
struct RealSet *e = makeSet(0.0, 1.0, BOTH_OPEN);
struct RealSet *f = makeSet(0.0, 1.0, CLOSED);
struct RealSet *g = makeSet(0.0, 0.0, CLOSED);
int i;
 
for (i = 0; i < 3; ++i) {
struct RealSet *t;
 
t = makeUnion(a, b);
printf("(0, 1] union [0, 2) contains %d is %d\n", i, t->contains(t, NULL, i));
free(t);
 
t = makeIntersect(b, c);
printf("[0, 2) intersect (1, 2] contains %d is %d\n", i, t->contains(t, NULL, i));
free(t);
 
t = makeSubtract(d, e);
printf("[0, 3) - (0, 1) contains %d is %d\n", i, t->contains(t, NULL, i));
free(t);
 
t = makeSubtract(d, f);
printf("[0, 3) - [0, 1] contains %d is %d\n", i, t->contains(t, NULL, i));
free(t);
 
printf("\n");
}
 
printf("[0, 0] is empty %d\n", empty(g));
 
free(a);
free(b);
free(c);
free(d);
free(e);
free(f);
free(g);
 
return 0;
}</syntaxhighlight>
{{out}}
<pre>(0, 1] union [0, 2) contains 0 is 1
[0, 2) intersect (1, 2] contains 0 is 0
[0, 3) - (0, 1) contains 0 is 1
[0, 3) - [0, 1] contains 0 is 0
 
(0, 1] union [0, 2) contains 1 is 1
[0, 2) intersect (1, 2] contains 1 is 0
[0, 3) - (0, 1) contains 1 is 1
[0, 3) - [0, 1] contains 1 is 0
 
(0, 1] union [0, 2) contains 2 is 0
[0, 2) intersect (1, 2] contains 2 is 0
[0, 3) - (0, 1) contains 2 is 1
[0, 3) - [0, 1] contains 2 is 1
 
[0, 0] is empty 0</pre>
 
=={{header|C sharp}}==
<langsyntaxhighlight lang="csharp">using System;
 
namespace RosettaCode.SetOfRealNumbers
Line 67 ⟶ 260:
}
}
}</langsyntaxhighlight>
Test:
<langsyntaxhighlight lang="csharp">using Microsoft.VisualStudio.TestTools.UnitTesting;
using RosettaCode.SetOfRealNumbers;
 
Line 117 ⟶ 310:
}
}
}</langsyntaxhighlight>
 
=={{header|C++}}==
{{trans|Java}}
<syntaxhighlight lang="cpp">#include <cassert>
#include <functional>
#include <iostream>
 
#define _USE_MATH_DEFINES
#include <math.h>
 
enum RangeType {
CLOSED,
BOTH_OPEN,
LEFT_OPEN,
RIGHT_OPEN
};
 
class RealSet {
private:
double low, high;
double interval = 0.00001;
std::function<bool(double)> predicate;
 
public:
RealSet(double low, double high, const std::function<bool(double)>& predicate) {
this->low = low;
this->high = high;
this->predicate = predicate;
}
 
RealSet(double start, double end, RangeType rangeType) {
low = start;
high = end;
 
switch (rangeType) {
case CLOSED:
predicate = [start, end](double d) { return start <= d && d <= end; };
break;
case BOTH_OPEN:
predicate = [start, end](double d) { return start < d && d < end; };
break;
case LEFT_OPEN:
predicate = [start, end](double d) { return start < d && d <= end; };
break;
case RIGHT_OPEN:
predicate = [start, end](double d) { return start <= d && d < end; };
break;
default:
assert(!"Unexpected range type encountered.");
}
}
 
bool contains(double d) const {
return predicate(d);
}
 
RealSet unionSet(const RealSet& rhs) const {
double low2 = fmin(low, rhs.low);
double high2 = fmax(high, rhs.high);
return RealSet(
low2, high2,
[this, &rhs](double d) { return predicate(d) || rhs.predicate(d); }
);
}
 
RealSet intersect(const RealSet& rhs) const {
double low2 = fmin(low, rhs.low);
double high2 = fmax(high, rhs.high);
return RealSet(
low2, high2,
[this, &rhs](double d) { return predicate(d) && rhs.predicate(d); }
);
}
 
RealSet subtract(const RealSet& rhs) const {
return RealSet(
low, high,
[this, &rhs](double d) { return predicate(d) && !rhs.predicate(d); }
);
}
 
double length() const {
if (isinf(low) || isinf(high)) return -1.0; // error value
if (high <= low) return 0.0;
 
double p = low;
int count = 0;
do {
if (predicate(p)) count++;
p += interval;
} while (p < high);
return count * interval;
}
 
bool empty() const {
if (high == low) {
return !predicate(low);
}
return length() == 0.0;
}
};
 
int main() {
using namespace std;
 
RealSet a(0.0, 1.0, LEFT_OPEN);
RealSet b(0.0, 2.0, RIGHT_OPEN);
RealSet c(1.0, 2.0, LEFT_OPEN);
RealSet d(0.0, 3.0, RIGHT_OPEN);
RealSet e(0.0, 1.0, BOTH_OPEN);
RealSet f(0.0, 1.0, CLOSED);
RealSet g(0.0, 0.0, CLOSED);
 
for (int i = 0; i <= 2; ++i) {
cout << "(0, 1] ∪ [0, 2) contains " << i << " is " << boolalpha << a.unionSet(b).contains(i) << "\n";
cout << "[0, 2) ∩ (1, 2] contains " << i << " is " << boolalpha << b.intersect(c).contains(i) << "\n";
cout << "[0, 3) - (0, 1) contains " << i << " is " << boolalpha << d.subtract(e).contains(i) << "\n";
cout << "[0, 3) - [0, 1] contains " << i << " is " << boolalpha << d.subtract(f).contains(i) << "\n";
cout << endl;
}
 
cout << "[0, 0] is empty is " << boolalpha << g.empty() << "\n";
cout << endl;
 
RealSet aa(
0.0, 10.0,
[](double x) { return (0.0 < x && x < 10.0) && abs(sin(M_PI * x * x)) > 0.5; }
);
RealSet bb(
0.0, 10.0,
[](double x) { return (0.0 < x && x < 10.0) && abs(sin(M_PI * x)) > 0.5; }
);
auto cc = aa.subtract(bb);
cout << "Approximate length of A - B is " << cc.length() << endl;
 
return 0;
}</syntaxhighlight>
{{out}}
<pre>(0, 1] ? [0, 2) contains 0 is true
[0, 2) ? (1, 2] contains 0 is false
[0, 3) - (0, 1) contains 0 is true
[0, 3) - [0, 1] contains 0 is false
 
(0, 1] ? [0, 2) contains 1 is true
[0, 2) ? (1, 2] contains 1 is false
[0, 3) - (0, 1) contains 1 is true
[0, 3) - [0, 1] contains 1 is false
 
(0, 1] ? [0, 2) contains 2 is false
[0, 2) ? (1, 2] contains 2 is false
[0, 3) - (0, 1) contains 2 is true
[0, 3) - [0, 1] contains 2 is true
 
[0, 0] is empty is false
 
Approximate length of A - B is 2.07587</pre>
 
=={{header|Clojure}}==
{{trans|Racket}}
<langsyntaxhighlight Clojurelang="clojure">(ns rosettacode.real-set)
 
(defn >=|<= [lo hi] #(<= lo % hi))
Line 154 ⟶ 503:
(def Q ratio?)
(def I #(∖ R Z Q))
(def N #(∖ Z neg?))</langsyntaxhighlight>
 
=={{header|Common Lisp}}==
Common Lisp has a standard way to represent intervals.
<syntaxhighlight lang="lisp">(deftype set== (a b) `(real ,a ,b))
(deftype set<> (a b) `(real (,a) (,b)))
(deftype set=> (a b) `(real ,a (,b)))
(deftype set<= (a b) `(real (,a) ,b))
 
(deftype set-union (s1 s2) `(or ,s1 ,s2))
(deftype set-intersection (s1 s2) `(and ,s1 ,s2))
(deftype set-diff (s1 s2) `(and ,s1 (not ,s2)))
 
(defun in-set-p (x set)
(typep x set))
 
(defun test ()
(let ((set '(set-union (set<= 0 1) (set=> 0 2))))
(assert (in-set-p 0 set))
(assert (in-set-p 1 set))
(assert (not (in-set-p 2 set))))
(let ((set '(set-intersection (set=> 0 2) (set<= 1 2))))
(assert (not (in-set-p 0 set)))
(assert (not (in-set-p 1 set)))
(assert (not (in-set-p 2 set))))
(let ((set '(set-diff (set=> 0 3) (set<> 0 1))))
(assert (in-set-p 0 set))
(assert (in-set-p 1 set))
(assert (in-set-p 2 set)))
(let ((set '(set-diff (set<= 0 3) (set== 0 1))))
(assert (not (in-set-p 0 set)))
(assert (not (in-set-p 1 set)))
(assert (in-set-p 2 set))))</syntaxhighlight>
 
=={{header|D}}==
{{trans|C sharp}}
<langsyntaxhighlight lang="d">struct Set(T) {
const pure nothrow bool delegate(in T) contains;
 
Line 218 ⟶ 599:
}
 
void main() {}</langsyntaxhighlight>
=={{header|ElenaDelphi}}==
{{libheader| System.SysUtils}}
<lang elena>#import system.
{{Trans|Go}}
#import extensions.
<syntaxhighlight lang="delphi">
program Set_of_real_numbers;
 
{$APPTYPE CONSOLE}
#class(extension)setOp
 
uses
System.SysUtils;
 
type
TSet = TFunc<Double, boolean>;
 
function Union(a, b: TSet): TSet;
begin
Result :=
function(x: double): boolean
begin
Result := a(x) or b(x);
end;
end;
 
function Inter(a, b: TSet): TSet;
begin
Result :=
function(x: double): boolean
begin
Result := a(x) and b(x);
end;
end;
 
function Diff(a, b: TSet): TSet;
begin
Result :=
function(x: double): boolean
begin
Result := a(x) and not b(x);
end;
end;
 
function Open(a, b: double): TSet;
begin
Result :=
function(x: double): boolean
begin
Result := (a < x) and (x < b);
end;
end;
 
function closed(a, b: double): TSet;
begin
Result :=
function(x: double): boolean
begin
Result := (a <= x) and (x <= b);
end;
end;
 
function opCl(a, b: double): TSet;
begin
Result :=
function(x: double): boolean
begin
Result := (a < x) and (x <= b);
end;
end;
 
function clOp(a, b: double): TSet;
begin
Result :=
function(x: double): boolean
begin
Result := (a <= x) and (x < b);
end;
end;
 
const
BOOLSTR: array[Boolean] of string = ('False', 'True');
 
begin
var s: TArray<TSet>;
SetLength(s, 4);
 
s[0] := Union(opCl(0, 1), clOp(0, 2)); // (0,1] ? [0,2)
s[1] := Inter(clOp(0, 2), opCl(1, 2)); // [0,2) n (1,2]
s[2] := Diff(clOp(0, 3), open(0, 1)); // [0,3) - (0,1)
s[3] := Diff(clOp(0, 3), closed(0, 1)); // [0,3) - [0,1]
 
for var i := 0 to High(s) do
begin
for var x := 0 to 2 do
writeln(format('%d e s%d: %s', [x, i, BOOLSTR[s[i](x)]]));
writeln;
end;
readln;
end.</syntaxhighlight>
 
=={{header|EchoLisp}}==
Implementation of sets operations, which apply to '''any''' subsets of ℜ defined by a predicate.
===Sets operations===
<syntaxhighlight lang="scheme">
(lib 'match) ;; reader-infix macros
 
(reader-infix '∈ )
(reader-infix '∩ )
(reader-infix '∪ )
(reader-infix '⊖ ) ;; set difference
(define-syntax-rule (∈ x a) (a x))
(define-syntax-rule (∩ a b) (lambda(x) (and ( a x) (b x))))
(define-syntax-rule (∪ a b) (lambda(x) (or ( a x) (b x))))
(define-syntax-rule (⊖ a b) (lambda(x) (and ( a x) (not (b x)))))
 
;; predicates to define common sets
(define (∅ x) #f) ;; the empty set predicate
(define (Z x) (integer? x))
(define (N x) (and (Z x) (>= x 0)))
(define (Q x) (rational? x))
(define (ℜ x) #t)
 
;; predicates to define convex sets
(define (⟦...⟧ a b)(lambda(x) (and (>= x a) (<= x b))))
(define (⟦...⟦ a b)(lambda(x) (and (>= x a) (< x b))))
(define (⟧...⟧ a b)(lambda(x) (and (> x a) (<= x b))))
(define (⟧...⟦ a b)(lambda(x) (and (> x a) (< x b))))
</syntaxhighlight>
{{out}}
<pre>
(3/7 ∈ ∅) → #f
(3/7 ∈ Q) → #t
(6.7 ∈ ℜ) → #t
 
(define A (⟦...⟧ 2 10)) ; closed interval
(define B (⟧...⟦ 5 15)) ; open interval
 
(8 ∈ A) → #t
(11 ∈ A)→ #f
(define AB (A ∩ B))
(8 ∈ AB) → #t
(3 ∈ AB) → #f
(5 ∈ AB) → #f ;; because B is ]5 .. 15]
(define A-B (A ⊖ B))
(5 ∈ A-B) → #t
(-666 ∈ (⟧...⟧ -Infinity 0 )) → #t
 
;; task
(0 ∈ ((⟧...⟧ 0 1) ∪ (⟦...⟦ 0 2))) → #t
(0 ∈ ((⟦...⟦ 0 2) ∩ (⟧...⟧ 1 2))) → #f
(0 ∈ ((⟦...⟦ 0 3) ⊖ (⟧...⟦ 0 1))) → #t
(0 ∈ ((⟦...⟦ 0 3) ⊖ (⟦...⟧ 0 1))) → #f
(1 ∈ ((⟧...⟧ 0 1) ∪ (⟦...⟦ 0 2))) → #t
(1 ∈ ((⟦...⟦ 0 2) ∩ (⟧...⟧ 1 2))) → #f
(1 ∈ ((⟦...⟦ 0 3) ⊖ (⟧...⟦ 0 1))) → #t
(1 ∈ ((⟦...⟦ 0 3) ⊖ (⟦...⟧ 0 1))) → #f
(2 ∈ ((⟧...⟧ 0 1) ∪ (⟦...⟦ 0 2))) → #f
(2 ∈ ((⟦...⟦ 0 2) ∩ (⟧...⟧ 1 2))) → #f
(2 ∈ ((⟦...⟦ 0 3) ⊖ (⟧...⟦ 0 1))) → #t
(2 ∈ ((⟦...⟦ 0 3) ⊖ (⟦...⟧ 0 1))) → #t
</pre>
=== Optional : measuring sets===
<syntaxhighlight lang="scheme">
;; The following applies to convex sets ⟧...⟦ Cx,
;; and families F of disjoint convex sets.
;; Cx are implemented as vectors [lo, hi]
 
(define-syntax-id _.lo [_ 0])
(define-syntax-id _.hi [_ 1])
;; Cx-ops
(define (Cx-new lo hi) (if (< lo hi) (vector lo hi) Cx-empty))
(define (Cx-empty? A) (>= A.lo A.hi))
(define Cx-empty #(+Infinity -Infinity))
(define (Cx-inter A B) (Cx-new (max A.lo B.lo) (min A.hi B.hi)))
(define (Cx-measure A) (if (< A.lo A.hi) (- A.hi A.lo) 0))
;; Families ops
(define (CF-measure FA) (for/sum ((A FA)) (Cx-measure A))) ;; because disjoint
;; intersection of two families
(define (CF-inter FA FB) (for*/list ((A FA)(B FB)) (Cx-inter A B)))
;; measure of FA/FB = m(FA) - m (FA ∩ FB)
(define (CF-measure-FA/FB FA FB)
(- (CF-measure FA) (CF-measure (CF-inter FA FB))))
;; Application :
;; FA = {x | 0 < x < 10 and |sin(π x²)| > 1/2 }
(define FA
(for/list ((n 100))
(Cx-new (sqrt (+ n (// 6))) (sqrt (+ n (// 5 6))))))
 
;; FB = {x | 0 < x < 10 and |sin(π x)| > 1/2 }
(define FB
(for/list ((n 10))
(Cx-new (+ n (// 6)) (+ n (// 5 6)))))
 
→ (#(0.1667 0.8333) #(1.1667 1.8333) #(2.1667 2.8333)
#(3.1667 3.8333) #(4.1667 4.8333) #(5.1667 5.8333)
#(6.1667 6.8333) #(7.1667 7.8333) #(8.1667 8.8333) #(9.1667 9.8333))
(CF-measure-FA/FB FA FB)
→ 2.075864841184666
 
</syntaxhighlight>
 
=={{header|Elena}}==
ELENA 6.x :
<syntaxhighlight lang="elena">import extensions;
extension setOp
{
#method union : (func)
= (val [=> self eval:(val) || func eval:(val) ].);
#method intersection : (func)
= (val [=> self eval:(val) && func eval:(val) ].);
#method difference : (func)
= (val [=> self eval:(val) && (func eval:(val)).Inverted not ].);
}
 
#symbolpublic program =()
{
[
// union
#var set := (x [=> (x >= 0.0r) && (x <= 1.0r) ] ).union: :(x [=> (x >= 0.0r) && (x < 2.0r ) ].;
set eval:(0.0r assert &ifTrue).assertTrue();
set eval:(1.0r assert &ifTrue).assertTrue();
set eval:(2.0r assert &ifFalse).assertFalse();
// intersection
#var set2 := (x [=> (x >= 0.0r) && (x < 2.0r) ] ).intersection: :(x [=> (x >= 1.0r) && (x <= 2.0r ) ].;
set2 eval:(0.0r assert &ifFalse).assertFalse();
set2 eval:(1.0r assert &ifTrue).assertTrue();
set2 eval:(2.0r assert &ifFalse).assertFalse();
// difference
#var set3 := (x [=> (x >= 0.0r) && (x < 3.0r) ] ).difference: :(x [=> (x >= 0.0r) && (x <= 1.0r ) ].;
set3 eval:(0.0r assert &ifFalse).assertFalse();
set3 eval:(1.0r assert &ifFalse).assertFalse();
set3 eval:(2.0r assert &ifTrue).assertTrue();
}</syntaxhighlight>
].</lang>
 
=={{header|FreeBASIC}}==
{{incomplete|FreeBASIC|Despite my efforts, the set difference results are erroneous.
 
I would appreciate help.}}
 
{{trans|Phix}}
<syntaxhighlight lang="vbnet">Type Func
As Integer ID
As Double ARGS(2)
End Type
 
Declare Function cf(f As Func, x As Double) As Boolean
Declare Function Union_(a As Func, b As Func, x As Double) As Boolean
Declare Function Inters(a As Func, b As Func, x As Double) As Boolean
Declare Function Differ(a As Func, b As Func, x As Double) As Boolean
Declare Function OpOp(a As Double, b As Double, x As Double) As Boolean
Declare Function ClCl(a As Double, b As Double, x As Double) As Boolean
Declare Function OpCl(a As Double, b As Double, x As Double) As Boolean
Declare Function ClOp(a As Double, b As Double, x As Double) As Boolean
Declare Function aspxx(a As Double) As Boolean
Declare Function aspx(a As Double) As Boolean
 
Function cf(f As Func, x As Double) As Boolean
Select Case f.ID
Case 1: Return OpOp(f.ARGS(0), f.ARGS(1), x)
Case 2: Return ClCl(f.ARGS(0), f.ARGS(1), x)
Case 3: Return OpCl(f.ARGS(0), f.ARGS(1), x)
Case 4: Return ClOp(f.ARGS(0), f.ARGS(1), x)
'Extra credit
Case 5: Return OpOp(f.ARGS(0), f.ARGS(1), x) And aspxx(x)
Case 6: Return OpOp(f.ARGS(0), f.ARGS(1), x) And aspx(x)
End Select
End Function
 
Function Union_(a As Func, b As Func, x As Double) As Boolean
Return cf(a, x) Or cf(b, x)
End Function
 
Function Inters(a As Func, b As Func, x As Double) As Boolean
Return cf(a, x) And cf(b, x)
End Function
 
Function Differ(a As Func, b As Func, x As Double) As Boolean
Return cf(a, x) And (Not cf(b, x))
End Function
 
Function OpOp(a As Double, b As Double, x As Double) As Boolean
Return a < x And x < b
End Function
 
Function ClCl(a As Double, b As Double, x As Double) As Boolean
Return a <= x And x <= b
End Function
 
Function OpCl(a As Double, b As Double, x As Double) As Boolean
Return a < x And x <= b
End Function
 
Function ClOp(a As Double, b As Double, x As Double) As Boolean
Return a <= x And x < b
End Function
 
'Extra credit
Function aspxx(a As Double) As Boolean
Return Abs(Sin(3.14159 * a * a)) > 0.5
End Function
 
Function aspx(a As Double) As Boolean
Return Abs(Sin(3.14159 * a)) > 0.5
End Function
 
' Set definitions and test methods
Dim As Func s(6, 2)
s(1, 0).ID = 3: s(1, 0).ARGS(0) = 0: s(1, 0).ARGS(1) = 1
s(1, 1).ID = 4: s(1, 1).ARGS(0) = 0: s(1, 1).ARGS(1) = 2
s(2, 0).ID = 4: s(2, 0).ARGS(0) = 0: s(2, 0).ARGS(1) = 2
s(2, 1).ID = 3: s(2, 1).ARGS(0) = 1: s(2, 1).ARGS(1) = 2
s(3, 0).ID = 4: s(3, 0).ARGS(0) = 0: s(3, 0).ARGS(1) = 3
s(3, 1).ID = 1: s(3, 1).ARGS(0) = 0: s(3, 1).ARGS(1) = 1
s(4, 0).ID = 4: s(4, 0).ARGS(0) = 0: s(4, 0).ARGS(1) = 3
s(4, 1).ID = 2: s(4, 1).ARGS(0) = 0: s(4, 1).ARGS(1) = 1
s(5, 0).ID = 2: s(5, 0).ARGS(0) = 0: s(5, 0).ARGS(1) = 0
'Extra credit
s(6, 1).ID = 5: s(6, 1).ARGS(0) = 0: s(6, 1).ARGS(1) = 10
s(6, 2).ID = 6: s(6, 2).ARGS(0) = 0: s(6, 2).ARGS(1) = 10
 
Dim As Integer i, x, r
For x = 0 To 2
i = 1
r = Union_(s(i, 1), s(i, 2), x)
Print Using "# in (#_,#] u [#_,#) : &"; x; s(i, 0).ARGS(0); s(i, 0).ARGS(1); s(i, 1).ARGS(0); s(1, 1).ARGS(1); Cbool(r)
Next x
Print
For x = 0 To 2
i = 2
r = Inters(s(i, 1), s(i, 2), x)
Print Using "# in (#_,#] u [#_,#) : &"; x; s(i, 0).ARGS(0); s(i, 0).ARGS(1); s(i, 1).ARGS(0); s(1, 1).ARGS(1); Cbool(r)
Next x
Print
For x = 0 To 2
i = 3
r = Differ(s(i, 1), s(i, 2), x)
Print Using "# in (#_,#] u [#_,#) : &"; x; s(i, 0).ARGS(0); s(i, 0).ARGS(1); s(i, 1).ARGS(0); s(1, 1).ARGS(1); Cbool(r)
Next x
Print
For x = 0 To 2
i = 4
r = Differ(s(i, 1), s(i, 2), x)
Print Using "# in (#_,#] u [#_,#) : &"; x; s(i, 0).ARGS(0); s(i, 0).ARGS(1); s(i, 1).ARGS(0); s(1, 1).ARGS(1); Cbool(r)
Next x
Print
 
x = 0
i = 5
r = Differ(s(i, 1), s(i, 2), x)
Print Using "[#_,#] is empty : &"; s(i, 0).ARGS(0); s(i, 0).ARGS(1); Cbool(r)
Print
 
'Extra credit
Dim As Double z = 0, paso = 0.00001
Dim As Integer count = 0
While z <= 10
If Differ(s(6, 1), s(6, 2), z) Then count += 1
z += paso
Wend
Print "Approximate length of A-B: "; count * paso
 
Sleep</syntaxhighlight>
{{out}}
<pre>0 in (0,1] u [0,2) : true
1 in (0,1] u [0,2) : true
2 in (0,1] u [0,2) : false
 
0 in (0,2] u [1,2) : false
1 in (0,2] u [1,2) : false
2 in (0,2] u [1,2) : false
 
0 in (0,3] u [0,2) : false
1 in (0,3] u [0,2) : false
2 in (0,3] u [0,2) : false
 
0 in (0,3] u [0,2) : true
1 in (0,3] u [0,2) : true
2 in (0,3] u [0,2) : false
 
[0,0] is empty : false
 
Approximate length of A-B: 2.07586</pre>
 
=={{header|F#|F sharp}}==
<syntaxhighlight lang="fsharp">open System
 
let union s1 s2 =
fun x -> (s1 x) || (s2 x);
 
let difference s1 s2 =
fun x -> (s1 x) && not (s2 x)
 
let intersection s1 s2 =
fun x -> (s1 x) && (s2 x)
 
[<EntryPoint>]
let main _ =
//test set union
let u1 = union (fun x -> 0.0 < x && x <= 1.0) (fun x -> 0.0 <= x && x < 2.0)
assert (u1 0.0)
assert (u1 1.0)
assert (not (u1 2.0))
 
//test set difference
let d1 = difference (fun x -> 0.0 <= x && x < 3.0) (fun x -> 0.0 < x && x < 1.0)
assert (d1 0.0)
assert (not (d1 0.5))
assert (d1 1.0)
assert (d1 2.0)
 
let d2 = difference (fun x -> 0.0 <= x && x < 3.0) (fun x -> 0.0 <= x && x <= 1.0)
assert (not (d2 0.0))
assert (not (d2 1.0))
assert (d2 2.0)
 
let d3 = difference (fun x -> 0.0 <= x && x <= Double.PositiveInfinity) (fun x -> 1.0 <= x && x <= 2.0)
assert (d3 0.0)
assert (not (d3 1.5))
assert (d3 3.0)
 
//test set intersection
let i1 = intersection (fun x -> 0.0 <= x && x < 2.0) (fun x -> 1.0 < x && x <= 2.0)
assert (not (i1 0.0))
assert (not (i1 1.0))
assert (not (i1 2.0))
 
0 // return an integer exit code</syntaxhighlight>
 
=={{header|Go}}==
Just the non-optional part:
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 288 ⟶ 1,067:
fmt.Println()
}
}</langsyntaxhighlight>
[http://play.golang.org/p/YQ2GRBM4af Run in Go Playground].
{{out}}
Line 307 ⟶ 1,086:
2 ∈ s3: true</pre>
This simple implementation doesn't support lengths so the although the A, B, and A−B sets can be defined and tested (see below), they can't be used to implement the optional part.
<langsyntaxhighlight Golang="go"> A := Inter(open(0, 10), func(x float64) bool {
return math.Abs(math.Sin(math.Pi*x*x)) > .5
})
Line 317 ⟶ 1,096:
for x := float64(5.98); x < 6.025; x += 0.01 {
fmt.Printf("%.2f ∈ A−B: %t\n", x, C(x))
}</langsyntaxhighlight>
 
=={{header|Haskell}}==
<syntaxhighlight lang="haskell">
{- Not so functional representation of R sets (with IEEE Double), in a strange way -}
 
import Data.List
import Data.Maybe
 
data BracketType = OpenSub | ClosedSub
deriving (Show, Enum, Eq, Ord)
 
data RealInterval = RealInterval {left :: BracketType, right :: BracketType,
lowerBound :: Double, upperBound :: Double}
deriving (Eq)
 
type RealSet = [RealInterval]
posInf = 1.0/0.0 :: Double -- IEEE tricks
negInf = (-1.0/0.0) :: Double
set_R = RealInterval ClosedSub ClosedSub negInf posInf :: RealInterval
 
emptySet = [] :: [RealInterval]
 
instance Show RealInterval where
show x@(RealInterval _ _ y y')
| y == y' && (left x == right x) && (left x == ClosedSub) = "{" ++ (show y) ++ "}"
| otherwise = [['(', '[']!!(fromEnum $ left x)] ++ (show $ lowerBound x) ++
"," ++ (show $ upperBound x) ++ [[')', ']']!!(fromEnum $ right x)]
showList [x] = shows x
showList (h:t) = shows h . (" U " ++) . showList t
showList [] = (++ "(/)") -- empty set
 
construct_interval :: Char -> Double -> Double -> Char -> RealInterval
construct_interval '(' x y ')' = RealInterval OpenSub OpenSub x y
construct_interval '(' x y ']' = RealInterval OpenSub ClosedSub x y
construct_interval '[' x y ')' = RealInterval ClosedSub OpenSub x y
construct_interval _ x y _ = RealInterval ClosedSub ClosedSub x y
 
set_is_empty :: RealSet -> Bool
set_is_empty rs = (rs == emptySet)
 
set_in :: Double -> RealSet -> Bool
set_in x [] = False
set_in x rs =
isJust (find (\s ->
((lowerBound s < x) && (x < upperBound s)) ||
(x == lowerBound s && left s == ClosedSub) ||
(x == upperBound s && right s == ClosedSub))
rs)
 
-- max, min for pairs (double, bracket)
max_p :: (Double, BracketType) -> (Double, BracketType) -> (Double, BracketType)
min_p :: (Double, BracketType) -> (Double, BracketType) -> (Double, BracketType)
max_p p1@(x, y) p2@(x', y')
| x == x' = (x, max y y') -- closed is stronger than open
| x < x' = p2
| otherwise = p1
 
min_p p1@(x, y) p2@(x', y')
| x == x' = (x, min y y')
| x < x' = p1
| otherwise = p2
 
simple_intersection :: RealInterval -> RealInterval -> [RealInterval]
simple_intersection ri1@(RealInterval l_ri1 r_ri1 x1 y1) ri2@(RealInterval l_ri2 r_ri2 x2 y2)
| (y1 < x2) || (y2 < x1) = emptySet
| (y1 == x2) && ((fromEnum r_ri1) + (fromEnum l_ri2) /= 2) = emptySet
| (y2 == x1) && ((fromEnum r_ri2) + (fromEnum l_ri1) /= 2) = emptySet
| otherwise = let lb = if x1 == x2 then (x1, min l_ri1 l_ri2) else max_p (x1, l_ri1) (x2, l_ri2) in
let rb = min_p (y1, right ri1) (y2, right ri2) in
[RealInterval (snd lb) (snd rb) (fst lb) (fst rb)]
 
simple_union :: RealInterval -> RealInterval -> [RealInterval]
simple_union ri1@(RealInterval l_ri1 r_ri1 x1 y1) ri2@(RealInterval l_ri2 r_ri2 x2 y2)
| (y1 < x2) || (y2 < x1) = [ri2, ri1]
| (y1 == x2) && ((fromEnum r_ri1) + (fromEnum l_ri2) /= 2) = [ri1, ri2]
| (y2 == x1) && ((fromEnum r_ri2) + (fromEnum l_ri1) /= 2) = [ri1, ri2]
| otherwise = let lb = if x1 == x2 then (x1, max l_ri1 l_ri2) else min_p (x1, l_ri1) (x2, l_ri2) in
let rb = max_p (y1, right ri1) (y2, right ri2) in
[RealInterval (snd lb) (snd rb) (fst lb) (fst rb)]
 
simple_complement :: RealInterval -> [RealInterval]
simple_complement ri1@(RealInterval l_ri1 r_ri1 x1 y1) =
[(RealInterval ClosedSub (inv l_ri1) negInf x1), (RealInterval (inv r_ri1) ClosedSub y1 posInf)]
where
inv OpenSub = ClosedSub
inv ClosedSub = OpenSub
 
set_sort :: RealSet -> RealSet
set_sort rs =
sortBy
(\s1 s2 ->
let (lp, rp) = ((lowerBound s1, left s1), (lowerBound s2, left s2)) in
if max_p lp rp == lp then GT else LT)
rs
 
set_simplify :: RealSet -> RealSet
set_simplify [] = emptySet
set_simplify rs =
concat (map make_empty (set_sort (foldl
(\acc ri1 -> (simple_union (head acc) ri1) ++ (tail acc))
[head sorted_rs]
sorted_rs)))
where
sorted_rs = set_sort rs
make_empty ri@(RealInterval lb rb x y)
| x >= y && (lb /= rb || rb /= ClosedSub) = emptySet
| otherwise = [ri]
 
-- set operations
set_complement :: RealSet -> RealSet
set_union :: RealSet -> RealSet -> RealSet
set_intersection :: RealSet -> RealSet -> RealSet
set_difference :: RealSet -> RealSet -> RealSet
set_measure :: RealSet -> Double
 
set_complement rs =
foldl set_intersection [set_R] (map simple_complement rs)
set_union rs1 rs2 =
set_simplify (rs1 ++ rs2)
set_intersection rs1 rs2 =
set_simplify $ concat [simple_intersection s1 s2 | s1 <- rs1, s2 <- rs2]
set_difference rs1 rs2 =
set_intersection (set_complement rs2) rs1
set_measure rs =
foldl (\acc x -> acc + (upperBound x) - (lowerBound x)) 0.0 rs
 
-- test
test = map (\x -> [x]) [construct_interval '(' 0 1 ']', construct_interval '[' 0 2 ')',
construct_interval '[' 0 2 ')', construct_interval '(' 1 2 ']',
construct_interval '[' 0 3 ')', construct_interval '(' 0 1 ')',
construct_interval '[' 0 3 ')', construct_interval '[' 0 1 ']']
restest = [set_union (test!!0) (test!!1), set_intersection (test!!2) (test!!3),
set_difference (test!!4) (test!!5), set_difference (test!!6) (test!!7)]
isintest s =
mapM_
(\x -> putStrLn ((show x) ++ " is in " ++ (show s) ++ " : " ++ (show (set_in x s))))
[0, 1, 2]
 
testA = [construct_interval '(' (sqrt (n + (1.0/6))) (sqrt (n + (5.0/6))) ')' | n <- [0..99]]
testB = [construct_interval '(' (n + (1.0/6)) (n + (5.0/6)) ')' | n <- [0..9]]
 
main =
putStrLn ("union " ++ (show (test!!0)) ++ " " ++ (show (test!!1)) ++ " = " ++ (show (restest!!0))) >>
putStrLn ("inter " ++ (show (test!!2)) ++ " " ++ (show (test!!3)) ++ " = " ++ (show (restest!!1))) >>
putStrLn ("diff " ++ (show (test!!4)) ++ " " ++ (show (test!!5)) ++ " = " ++ (show (restest!!2))) >>
putStrLn ("diff " ++ (show (test!!6)) ++ " " ++ (show (test!!7)) ++ " = " ++ (show (restest!!3))) >>
mapM_ isintest restest >>
putStrLn ("measure: " ++ (show (set_measure (set_difference testA testB))))
</syntaxhighlight>
{{out}}
<pre>
union (0.0,1.0] [0.0,2.0) = [0.0,2.0)
inter [0.0,2.0) (1.0,2.0] = (1.0,2.0)
diff [0.0,3.0) (0.0,1.0) = {0.0} U [1.0,3.0)
diff [0.0,3.0) [0.0,1.0] = (1.0,3.0)
0.0 is in [0.0,2.0) : True
1.0 is in [0.0,2.0) : True
2.0 is in [0.0,2.0) : False
0.0 is in (1.0,2.0) : False
1.0 is in (1.0,2.0) : False
2.0 is in (1.0,2.0) : False
0.0 is in {0.0} U [1.0,3.0) : True
1.0 is in {0.0} U [1.0,3.0) : True
2.0 is in {0.0} U [1.0,3.0) : True
0.0 is in (1.0,3.0) : False
1.0 is in (1.0,3.0) : False
2.0 is in (1.0,3.0) : True
measure: 2.0758648411846696
</pre>
 
==Icon and {{header|Unicon}}==
Line 324 ⟶ 1,272:
simplifications of some representations, but more could be done.
 
<langsyntaxhighlight lang="unicon">procedure main(A)
s1 := RealSet("(0,1]").union(RealSet("[0,2)"))
s2 := RealSet("[0,2)").intersect(RealSet("(1,2)"))
Line 423 ⟶ 1,371:
initially(s)
put(ranges := [],Range(\s).notEmpty())
end</langsyntaxhighlight>
 
Sample run:
Line 451 ⟶ 1,399:
In essence, this looks like building a restricted set of statements. So we build a specialized parser and expression builder:
 
<langsyntaxhighlight lang="j">has=: 1 :'(interval m)`:6'
ing=: `''
Line 467 ⟶ 1,415:
union=: 4 :'(x has +. y has)ing'
intersect=: 4 :'(x has *. y has)ing'
without=: 4 :'(x has *. [: -. y has)ing'</langsyntaxhighlight>
 
With this in place, the required examples look like this:
 
<langsyntaxhighlight lang="j"> ('(0,1]' union '[0,2)')has 0 1 2
1 1 0
('[0,2)' intersect '(1,2]')has 0 1 2
Line 480 ⟶ 1,428:
1 1 1
('[0,3)' without '[0,1]')has 0 1 2
0 0 1</langsyntaxhighlight>
 
Note that without the arguments these wind up being expressions. For example:
 
<langsyntaxhighlight lang="j"> ('(0,1]' union '[0,2)')has
(0&< *. 1&>:) +. 0&<: *. 2&></langsyntaxhighlight>
 
In other words, this is a statement built up from inequality terminals (where each inequality is bound to a constant) and the terminals are combined with logical operations.
Line 495 ⟶ 1,443:
Here is an alternate formulation which allows detection of empty sets:
 
<langsyntaxhighlight lang="j">has=: 1 :'(0 {:: interval m)`:6'
ing=: `''
 
Line 513 ⟶ 1,461:
)
 
in=: 4 :'y has x'
union=: 4 :'(x has +. y has)ing; x edges y'
intersect=: 4 :'(x has *. y has)ing; x edges y'
without=: 4 :'(x has *. [: -. y has)ing; x edges y'
in=: 4 :'y has x'
isEmpty=: 1 -.@e. contour in ]</lang>
isEmpty=: 1 -.@e. contour in ]</syntaxhighlight>
 
The above examples work identically with this version, but also:
 
<langsyntaxhighlight lang="j"> isEmpty '(0,1]' union '[0,2)'
0
isEmpty '[0,2)' intersect '(1,2]'
Line 530 ⟶ 1,478:
1
isEmpty '[0,2]' intersect '[2,3]'
0</langsyntaxhighlight>
 
Note that the the set operations no longer return a simple verb -- instead, they return a pair, where the first element represents the verb and the second element is a list of interval boundaries. We can tell if two adjacent bounds, from this list, bound a valid interval by checking any point between them.
Line 538 ⟶ 1,486:
The optional work centers around expressions where the absolute value of sin pi * n is 0.5. It would be nice if J had an arcsine which gave all values within a range, but it does not have that. So:
 
<langsyntaxhighlight lang="j"> 1p_1 * _1 o. 0.5
0.166667</langsyntaxhighlight>
 
(Note on notation: 1 o. is sine in J, and 2 o. is cosine -- the mnemonic is that sine is an odd function and cosine is an even function, the practical value is that sine, cosine and sine/cosine pairs can all be generated from the same "real" valued function.
Similarly, _1 o. is arcsine and _2 o. is arcsine. Also 1p_1 is the reciprocal of pi. So the above tells us that the principal value for arc sine 0.5 is one sixth.)
 
<langsyntaxhighlight lang="j"> (#~ 0.5 = 1 |@o. 1r6p1&*) i. 30
1 5 7 11 13 17 19 23 25 29
2 -~/\ (#~ 0.5 = 1 |@o. 1r6p1&*) i. 30
4 2 4 2 4 2 4 2 4</langsyntaxhighlight>
 
Here we see the integers which when multiplied by pi/6 give 0.5 for the absolute value of the sine, and their first difference. Thus:
 
<langsyntaxhighlight lang="j">zeros0toN=: ((>: # ])[:+/\1,$&4 2@<.)&.(6&*)</langsyntaxhighlight>
 
is a function to generate the values which correspond to the boundaries of the intervals we want:
 
<langsyntaxhighlight lang="j">zB=: zeros0toN 10
zA=: zeros0toN&.*: 10
 
Line 565 ⟶ 1,513:
200
#zB
20</langsyntaxhighlight>
 
And, here are the edges of the sets of intervals we need to consider.
Line 571 ⟶ 1,519:
To find the length of the the set A-B we can find the length of set A and subtract the length of the set A-B:
 
<langsyntaxhighlight lang="j"> (+/_2 -~/\zA) - +/,0>.zA (<.&{: - >.&{.)"1/&(_2 ]\ ]) zB
2.07586</langsyntaxhighlight>
 
Here, we have paired adjacent elements from the zero bounding list (non-overlapping infixes of length 2). For set A's length we sum the results of subtracting the smaller number of the pair from the larger. For set A-B's length we consider each combination of pairs from A and B and subtract the larger of the beginning values from the smaller of the ending values (and ignore any negative results).
Line 578 ⟶ 1,526:
Alternatively, if we use the set implementation with empty set detection, and the following definitions:
 
<langsyntaxhighlight lang="j">intervalSet=: interval@('[',[,',',],')'"_)&":
A=: union/_2 intervalSet/\ zA
B=: union/_2 intervalSet/\ zB
diff=: A without B</langsyntaxhighlight>
 
We can replace the above sentence to compute the length of the difference with:
 
<langsyntaxhighlight lang="j"> +/ ((2 (+/%#)\ edge diff) in diff) * 2 -~/\ edge diff
2.07588</langsyntaxhighlight>
 
(Note that this result is not exactly the same as the previous result. Determining why would be an interesting exercise in numerical analysis.)
 
=={{header|MathematicaJava}}==
<syntaxhighlight lang="java">import java.util.Objects;
<lang Mathematica>(* defining functions *)
import java.util.function.Predicate;
 
public class RealNumberSet {
public enum RangeType {
CLOSED,
BOTH_OPEN,
LEFT_OPEN,
RIGHT_OPEN,
}
 
public static class RealSet {
private Double low;
private Double high;
private Predicate<Double> predicate;
private double interval = 0.00001;
 
public RealSet(Double low, Double high, Predicate<Double> predicate) {
this.low = low;
this.high = high;
this.predicate = predicate;
}
 
public RealSet(Double start, Double end, RangeType rangeType) {
this(start, end, d -> {
switch (rangeType) {
case CLOSED:
return start <= d && d <= end;
case BOTH_OPEN:
return start < d && d < end;
case LEFT_OPEN:
return start < d && d <= end;
case RIGHT_OPEN:
return start <= d && d < end;
default:
throw new IllegalStateException("Unhandled range type encountered.");
}
});
}
 
public boolean contains(Double d) {
return predicate.test(d);
}
 
public RealSet union(RealSet other) {
double low2 = Math.min(low, other.low);
double high2 = Math.max(high, other.high);
return new RealSet(low2, high2, d -> predicate.or(other.predicate).test(d));
}
 
public RealSet intersect(RealSet other) {
double low2 = Math.min(low, other.low);
double high2 = Math.max(high, other.high);
return new RealSet(low2, high2, d -> predicate.and(other.predicate).test(d));
}
 
public RealSet subtract(RealSet other) {
return new RealSet(low, high, d -> predicate.and(other.predicate.negate()).test(d));
}
 
public double length() {
if (low.isInfinite() || high.isInfinite()) return -1.0; // error value
if (high <= low) return 0.0;
Double p = low;
int count = 0;
do {
if (predicate.test(p)) count++;
p += interval;
} while (p < high);
return count * interval;
}
 
public boolean isEmpty() {
if (Objects.equals(high, low)) {
return predicate.negate().test(low);
}
return length() == 0.0;
}
}
 
public static void main(String[] args) {
RealSet a = new RealSet(0.0, 1.0, RangeType.LEFT_OPEN);
RealSet b = new RealSet(0.0, 2.0, RangeType.RIGHT_OPEN);
RealSet c = new RealSet(1.0, 2.0, RangeType.LEFT_OPEN);
RealSet d = new RealSet(0.0, 3.0, RangeType.RIGHT_OPEN);
RealSet e = new RealSet(0.0, 1.0, RangeType.BOTH_OPEN);
RealSet f = new RealSet(0.0, 1.0, RangeType.CLOSED);
RealSet g = new RealSet(0.0, 0.0, RangeType.CLOSED);
 
for (int i = 0; i <= 2; i++) {
Double dd = (double) i;
System.out.printf("(0, 1] ∪ [0, 2) contains %d is %s\n", i, a.union(b).contains(dd));
System.out.printf("[0, 2) ∩ (1, 2] contains %d is %s\n", i, b.intersect(c).contains(dd));
System.out.printf("[0, 3) − (0, 1) contains %d is %s\n", i, d.subtract(e).contains(dd));
System.out.printf("[0, 3) − [0, 1] contains %d is %s\n", i, d.subtract(f).contains(dd));
System.out.println();
}
 
System.out.printf("[0, 0] is empty is %s\n", g.isEmpty());
System.out.println();
 
RealSet aa = new RealSet(
0.0, 10.0,
x -> (0.0 < x && x < 10.0) && Math.abs(Math.sin(Math.PI * x * x)) > 0.5
);
RealSet bb = new RealSet(
0.0, 10.0,
x -> (0.0 < x && x < 10.0) && Math.abs(Math.sin(Math.PI * x)) > 0.5
);
RealSet cc = aa.subtract(bb);
System.out.printf("Approx length of A - B is %f\n", cc.length());
}
}</syntaxhighlight>
{{out}}
<pre>(0, 1] ∪ [0, 2) contains 0 is true
[0, 2) ∩ (1, 2] contains 0 is false
[0, 3) − (0, 1) contains 0 is true
[0, 3) − [0, 1] contains 0 is false
 
(0, 1] ∪ [0, 2) contains 1 is true
[0, 2) ∩ (1, 2] contains 1 is false
[0, 3) − (0, 1) contains 1 is true
[0, 3) − [0, 1] contains 1 is false
 
(0, 1] ∪ [0, 2) contains 2 is false
[0, 2) ∩ (1, 2] contains 2 is false
[0, 3) − (0, 1) contains 2 is true
[0, 3) − [0, 1] contains 2 is true
 
[0, 0] is empty is false
 
Approx length of A - B is 2.075870</pre>
 
=={{header|Javascript}}==
<syntaxhighlight lang="javascript">
function realSet(set1, set2, op, values) {
const makeSet=(set0)=>{
let res = []
if(set0.rangeType===0){
for(let i=set0.low;i<=set0.high;i++)
res.push(i);
} else if (set0.rangeType===1) {
for(let i=set0.low+1;i<set0.high;i++)
res.push(i);
} else if(set0.rangeType===2){
for(let i=set0.low+1;i<=set0.high;i++)
res.push(i);
} else {
for(let i=set0.low;i<set0.high;i++)
res.push(i);
}
return res;
}
let res = [],finalSet=[];
set1 = makeSet(set1);
set2 = makeSet(set2);
if(op==="union")
finalSet = [...new Set([...set1,...set2])];
else if(op==="intersect") {
for(let i=0;i<set1.length;i++)
if(set1.indexOf(set2[i])!==-1)
finalSet.push(set2[i]);
} else {
for(let i=0;i<set2.length;i++)
if(set1.indexOf(set2[i])===-1)
finalSet.push(set2[i]);
 
for(let i=0;i<set1.length;i++)
if(set2.indexOf(set1[i])===-1)
finalSet.push(set1[i]);
}
for(let i=0;i<values.length;i++){
if(finalSet.indexOf(values[i])!==-1)
res.push(true);
else
res.push(false);
}
return res;
}
</syntaxhighlight>
 
=={{header|jq}}==
{{works with|jq}}
 
'''Works with gojq, the Go implementation of jq provided `keys_unsorted` is replaced with `keys`'''
 
This entry focuses on functions that operate on "real sets" and not
just intervals of the real number line, it being understood that a
"real set" in the present context is a finite union of such intervals,
in accordance with the problem description.
 
Since every "real set" in this sense can be represented in canonical form as
a finite disjoint union of intervals, we will use the term RealSet
to denote a canonical representation in jq of a "real set" as follows:
 
A RealSet is a jq array consisting of numbers and/or two-element arrays
[a,b], where a and b are numbers with a < b, where:
 
* each number represents the closed interval containing that number;
* each array [a,b] represents the open interval from a to b exclusive;
* the items in the outer array are sorted in ascending order in the obvious way.
 
The jq values `infinite` and `-infinite` are also allowed, thus allowing infinite
intervals to be represented.
 
Examples:
 
* [] representes the empty RealSet.
* [[1,2]] represents the RealSet consisting of the open interval from 1 to 2 exclusive.
* [1, [1,2], 2] represents the closed interval from 1 to 2 inclusive.
* [1,2] represents the union of the two closed intervals containing respectively 1 and 2.
* [-infinite, 0] represents the open interval consisting of the finite negative numbers.
* [infinite] represents the closed interval whose only element is positive inifinity.
 
For clarity and to facilitate reuse, the RealSet function definitions are bundled
together in a jq module, RealSet, available at
[[:Category:Jq/RealSet.jq]]. Here we summarize the key functions and illustrate their use.
 
1) To convert an arbitrary union of real intervals to a RealSet,
use `RealSet/0`, e.g.
 
[ [1,5], [2,6] ] | RealSet #=> [[1,6]]
 
2) Testing whether a RealSet is empty
 
Since the empty RealSet is just [], there is no real need to define
a function for testing whether a RealSet is empty. To test
whether an arbitrary union of real intervals is empty,
use the idiom:
 
RealSet == []
 
For example:
 
[ [1,3], [0,1] ] | RealSet == [] #=> false
 
3) To check whether a specific number, $r, is in a RealSet,
one can use `containsNumber($r)`, and similarly to check
whether an open interval is in a RealSet, one can
use `containsOpenInterval($a; $b)` where $a < $b defines
the open interval.
 
4) The basic binary operations on RealSets are:
 
add/1
intersection/1
minus/1
 
5) To compute the length of a RealSet: `RealSetLength/0`
 
This returns `infinite` if any component interval is infinite.
 
===Tasks===
<syntaxhighlight lang="jq">
include "realset" {search: "."};
 
def test_cases:
{ "(0, 1] ∪ [0, 2)": ( [ [0,1], 1] | add( [0, [0,2]] )),
"[0, 2) ∩ (1, 2]": ( [ 0, [0,2]] | intersection( [[1,2],2] ) ),
"[0, 3) − (0, 1)": ( [ 0, [0,3]] | minus( [[0,1]] ) ),
"[0, 3) − [0, 1]": ( [ 0, [0,3]] | minus( [0, [0,1], 1] ))
} ;
 
def keys_unsorted: keys; # for gojq
 
def tests($values):
"Checking containment of: \($values | join(" "))",
(keys_unsorted[] as $name
| "\($name) has length \(.[$name]|RealSetLength) and contains: \( [$values[] as $i | select(.[$name] | containsNumber($i) ) | $i] | join(" ") )" )
;
 
# A and B
def pi: 1 | atan * 4;
 
# For positive integers $n,
# we define B($n) to correspond to {x | 0 < x < $n and |sin(π x)| > 1/2}
def B($upper):
def x: 0.5 | asin / pi;
x as $x
| reduce range(0; $upper) as $i ([];
. + [ [$i + $x, $i + 1 - $x]]);
 
# |sin(π x²)| > 1/2
def A($upper):
B($upper * $upper) | map( map(sqrt) );
 
# The simple tests:
test_cases | tests([0,1,2]),
 
# A - B
"|A - B| = \(A(10) | minus( B(10) ) | RealSetLength)"
 
</syntaxhighlight>
{{output}}
<pre>
Checking containment of: 0 1 2
(0, 1] ∪ [0, 2) has length 2 and contains: 0 1
[0, 2) ∩ (1, 2] has length 1 and contains:
[0, 3) − (0, 1) has length 2 and contains: 0 1 2
[0, 3) − [0, 1] has length 2 and contains: 2
|A - B| = 2.075864841184667
</pre>
 
=={{header|Julia}}==
<syntaxhighlight lang="julia">
"""
struct ConvexRealSet
Convex real set (similar to a line segment).
Parameters: lower bound, upper bound: floating point numbers
includelower, includeupper: boolean true or false to indicate whether
the set has a closed boundary (set to true) or open (set to false).
"""
mutable struct ConvexRealSet
lower::Float64
includelower::Bool
upper::Float64
includeupper::Bool
function ConvexRealSet(lo, up, incllo, inclup)
this = new()
this.upper = Float64(up)
this.lower = Float64(lo)
this.includelower = incllo
this.includeupper = inclup
this
end
end
 
 
function ∈(s, xelem)
x = Float64(xelem)
if(x == s.lower)
if(s.includelower)
return true
else
return false
end
elseif(x == s.upper)
if(s.includeupper)
return true
else
return false
end
end
s.lower < x && x < s.upper
end
 
 
⋃(aset, bset, x) = (∈(aset, x) || ∈(bset, x))
 
⋂(aset, bset, x) = (∈(aset, x) && ∈(bset, x))
 
-(aset, bset, x) = (∈(aset, x) && !∈(bset, x))
 
isempty(s::ConvexRealSet) = (s.lower > s.upper) ||
((s.lower == s.upper) && !s.includeupper && !s.includelower)
 
 
const s1 = ConvexRealSet(0.0, 1.0, false, true)
const s2 = ConvexRealSet(0.0, 2.0, true, false)
const s3 = ConvexRealSet(1.0, 2.0, false, true)
const s4 = ConvexRealSet(0.0, 3.0, true, false)
const s5 = ConvexRealSet(0.0, 1.0, false, false)
const s6 = ConvexRealSet(0.0, 1.0, true, true)
const sempty = ConvexRealSet(0.0, -1.0, true, true)
const testlist = [0, 1, 2]
 
 
function testconvexrealset()
for i in testlist
println("Testing with x = $i.\nResults:")
println(" (0, 1] ∪ [0, 2): $(⋃(s1, s2, i))")
println(" [0, 2) ∩ (1, 2]: $(⋂(s2, s3, i))")
println(" [0, 3) − (0, 1): $(-(s4, s5, i))")
println(" [0, 3) − [0, 1]: $(-(s4, s6, i))\n")
end
print("The set sempty is ")
println(isempty(sempty) ? "empty." : "not empty.")
end
 
 
testconvexrealset()
</syntaxhighlight>
{{output}}<pre>
Testing with x = 0.
Results:
(0, 1] ∪ [0, 2): true
[0, 2) ∩ (1, 2]: false
[0, 3) − (0, 1): true
[0, 3) − [0, 1]: false
 
Testing with x = 1.
Results:
(0, 1] ∪ [0, 2): true
[0, 2) ∩ (1, 2]: false
[0, 3) − (0, 1): true
[0, 3) − [0, 1]: false
 
Testing with x = 2.
Results:
(0, 1] ∪ [0, 2): false
[0, 2) ∩ (1, 2]: false
[0, 3) − (0, 1): true
[0, 3) − [0, 1]: true
 
The set sempty is empty.
</pre>
 
=={{header|Kotlin}}==
The RealSet class has two constructors - a primary one which creates an object for an arbitrary predicate and a secondary one which creates an object for a simple range by generating the appropriate predicate and then invoking the primary one.
 
As far as the optional work is concerned, I decided to add a length property which gives only an approximate result. Basically, it works by keeping track of the low and high values of the set and then counting points at successive small intervals between these limits which satisfy the predicate. An isEmpty() function has also been added but as this depends, to some extent, on the length property it is not 100% reliable.
 
Clearly, the above approach is only suitable for sets with narrow ranges (as we have here) but does have the merit of not over-complicating the basic class.
<syntaxhighlight lang="scala">// version 1.1.4-3
 
typealias RealPredicate = (Double) -> Boolean
 
enum class RangeType { CLOSED, BOTH_OPEN, LEFT_OPEN, RIGHT_OPEN }
 
class RealSet(val low: Double, val high: Double, val predicate: RealPredicate) {
 
constructor (start: Double, end: Double, rangeType: RangeType): this(start, end,
when (rangeType) {
RangeType.CLOSED -> fun(d: Double) = d in start..end
RangeType.BOTH_OPEN -> fun(d: Double) = start < d && d < end
RangeType.LEFT_OPEN -> fun(d: Double) = start < d && d <= end
RangeType.RIGHT_OPEN -> fun(d: Double) = start <= d && d < end
}
)
 
fun contains(d: Double) = predicate(d)
 
infix fun union(other: RealSet): RealSet {
val low2 = minOf(low, other.low)
val high2 = maxOf(high, other.high)
return RealSet(low2, high2) { predicate(it) || other.predicate(it) }
}
infix fun intersect(other: RealSet): RealSet {
val low2 = maxOf(low, other.low)
val high2 = minOf(high, other.high)
return RealSet(low2, high2) { predicate(it) && other.predicate(it) }
}
 
infix fun subtract(other: RealSet) = RealSet(low, high) { predicate(it) && !other.predicate(it) }
 
var interval = 0.00001
 
val length: Double get() {
if (!low.isFinite() || !high.isFinite()) return -1.0 // error value
if (high <= low) return 0.0
var p = low
var count = 0
do {
if (predicate(p)) count++
p += interval
}
while (p < high)
return count * interval
}
 
fun isEmpty() = if (high == low) !predicate(low) else length == 0.0
}
 
fun main(args: Array<String>) {
val a = RealSet(0.0, 1.0, RangeType.LEFT_OPEN)
val b = RealSet(0.0, 2.0, RangeType.RIGHT_OPEN)
val c = RealSet(1.0, 2.0, RangeType.LEFT_OPEN)
val d = RealSet(0.0, 3.0, RangeType.RIGHT_OPEN)
val e = RealSet(0.0, 1.0, RangeType.BOTH_OPEN)
val f = RealSet(0.0, 1.0, RangeType.CLOSED)
val g = RealSet(0.0, 0.0, RangeType.CLOSED)
 
for (i in 0..2) {
val dd = i.toDouble()
println("(0, 1] ∪ [0, 2) contains $i is ${(a union b).contains(dd)}")
println("[0, 2) ∩ (1, 2] contains $i is ${(b intersect c).contains(dd)}")
println("[0, 3) − (0, 1) contains $i is ${(d subtract e).contains(dd)}")
println("[0, 3) − [0, 1] contains $i is ${(d subtract f).contains(dd)}\n")
}
 
println("[0, 0] is empty is ${g.isEmpty()}\n")
 
val aa = RealSet(0.0, 10.0) { x -> (0.0 < x && x < 10.0) &&
Math.abs(Math.sin(Math.PI * x * x)) > 0.5 }
val bb = RealSet(0.0, 10.0) { x -> (0.0 < x && x < 10.0) &&
Math.abs(Math.sin(Math.PI * x)) > 0.5 }
val cc = aa subtract bb
println("Approx length of A - B is ${cc.length}")
}</syntaxhighlight>
 
{{out}}
<pre>
(0, 1] ∪ [0, 2) contains 0 is true
[0, 2) ∩ (1, 2] contains 0 is false
[0, 3) − (0, 1) contains 0 is true
[0, 3) − [0, 1] contains 0 is false
 
(0, 1] ∪ [0, 2) contains 1 is true
[0, 2) ∩ (1, 2] contains 1 is false
[0, 3) − (0, 1) contains 1 is true
[0, 3) − [0, 1] contains 1 is false
 
(0, 1] ∪ [0, 2) contains 2 is false
[0, 2) ∩ (1, 2] contains 2 is false
[0, 3) − (0, 1) contains 2 is true
[0, 3) − [0, 1] contains 2 is true
 
[0, 0] is empty is false
 
Approx length of A - B is 2.07587
</pre>
 
=={{header|Lua}}==
<syntaxhighlight lang="lua">function createSet(low,high,rt)
local l,h = tonumber(low), tonumber(high)
if l and h then
local t = {low=l, high=h}
 
if type(rt) == "string" then
if rt == "open" then
t.contains = function(d) return low< d and d< high end
elseif rt == "closed" then
t.contains = function(d) return low<=d and d<=high end
elseif rt == "left" then
t.contains = function(d) return low< d and d<=high end
elseif rt == "right" then
t.contains = function(d) return low<=d and d< high end
else
error("Unknown range type: "..rt)
end
elseif type(rt) == "function" then
t.contains = rt
else
error("Unable to find a range type or predicate")
end
 
t.union = function(o)
local l2 = math.min(l, o.low)
local h2 = math.min(h, o.high)
local p = function(d) return t.contains(d) or o.contains(d) end
return createSet(l2, h2, p)
end
 
t.intersect = function(o)
local l2 = math.min(l, o.low)
local h2 = math.min(h, o.high)
local p = function(d) return t.contains(d) and o.contains(d) end
return createSet(l2, h2, p)
end
 
t.subtract = function(o)
local l2 = math.min(l, o.low)
local h2 = math.min(h, o.high)
local p = function(d) return t.contains(d) and not o.contains(d) end
return createSet(l2, h2, p)
end
 
t.length = function()
if h <= l then return 0.0 end
local p = l
local count = 0
local interval = 0.00001
repeat
if t.contains(p) then count = count + 1 end
p = p + interval
until p>=high
return count * interval
end
 
t.empty = function()
if l == h then
return not t.contains(low)
end
return t.length() == 0.0
end
 
return t
else
error("Either '"..low.."' or '"..high.."' is not a number")
end
end
 
local a = createSet(0.0, 1.0, "left")
local b = createSet(0.0, 2.0, "right")
local c = createSet(1.0, 2.0, "left")
local d = createSet(0.0, 3.0, "right")
local e = createSet(0.0, 1.0, "open")
local f = createSet(0.0, 1.0, "closed")
local g = createSet(0.0, 0.0, "closed")
 
for i=0,2 do
print("(0, 1] union [0, 2) contains "..i.." is "..tostring(a.union(b).contains(i)))
print("[0, 2) intersect (1, 2] contains "..i.." is "..tostring(b.intersect(c).contains(i)))
print("[0, 3) - (0, 1) contains "..i.." is "..tostring(d.subtract(e).contains(i)))
print("[0, 3) - [0, 1] contains "..i.." is "..tostring(d.subtract(f).contains(i)))
print()
end
 
print("[0, 0] is empty is "..tostring(g.empty()))
print()
 
local aa = createSet(
0.0, 10.0,
function(x) return (0.0<x and x<10.0) and math.abs(math.sin(math.pi * x * x)) > 0.5 end
)
local bb = createSet(
0.0, 10.0,
function(x) return (0.0<x and x<10.0) and math.abs(math.sin(math.pi * x)) > 0.5 end
)
local cc = aa.subtract(bb)
print("Approx length of A - B is "..cc.length())</syntaxhighlight>
{{out}}
<pre>(0, 1] union [0, 2) contains 0 is true
[0, 2) intersect (1, 2] contains 0 is false
[0, 3) - (0, 1) contains 0 is true
[0, 3) - [0, 1] contains 0 is false
 
(0, 1] union [0, 2) contains 1 is true
[0, 2) intersect (1, 2] contains 1 is false
[0, 3) - (0, 1) contains 1 is true
[0, 3) - [0, 1] contains 1 is false
 
(0, 1] union [0, 2) contains 2 is false
[0, 2) intersect (1, 2] contains 2 is false
[0, 3) - (0, 1) contains 2 is true
[0, 3) - [0, 1] contains 2 is true
 
[0, 0] is empty is false
 
Approx length of A - B is 2.07587</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">(* defining functions *)
setcc[a_, b_] := a <= x <= b
setoo[a_, b_] := a < x < b
Line 617 ⟶ 2,198:
Print[set4]
Print["Fourth trial set, [0,3)\[Minus][0,1], testing for {0,1,2}:"]
Print[inSetQ[#, set4] & /@ {0, 1, 2}]</langsyntaxhighlight>
{{Output}}
<pre>0<x<=1||0<=x<2
Line 635 ⟶ 2,216:
{False,False,True}</pre>
 
=={{header|Nim}}==
{{trans|Kotlin}}
<syntaxhighlight lang="nim">import math, strformat, sugar
 
type
 
RealPredicate = (float) -> bool
 
RangeType {.pure} = enum Closed, BothOpen, LeftOpen, RightOpen
 
RealSet = object
low, high: float
predicate: RealPredicate
 
 
proc initRealSet(slice: Slice[float]; rangeType: RangeType): RealSet =
result = RealSet(low: slice.a, high: slice.b)
result.predicate = case rangeType
of Closed: (x: float) => x in slice
of BothOpen: (x: float) => slice.a < x and x < slice.b
of LeftOpen: (x: float) => slice.a < x and x <= slice.b
of RightOpen: (x: float) => slice.a <= x and x < slice.b
 
 
proc contains(s: RealSet; val: float): bool =
## Defining "contains" makes operator "in" available.
s.predicate(val)
 
 
proc `+`(s1, s2: RealSet): RealSet =
RealSet(low: min(s1.low, s2.low), high: max(s1.high, s2.high),
predicate: (x:float) => s1.predicate(x) or s2.predicate(x))
 
 
proc `*`(s1, s2: RealSet): RealSet =
RealSet(low: max(s1.low, s2.low), high: min(s1.high, s2.high),
predicate: (x:float) => s1.predicate(x) and s2.predicate(x))
 
 
proc `-`(s1, s2: RealSet): RealSet =
RealSet(low: s1.low, high: s1.high,
predicate: (x:float) => s1.predicate(x) and not s2.predicate(x))
 
 
const Interval = 0.00001
 
proc length(s: RealSet): float =
if s.low.classify() in {fcInf, fcNegInf} or s.high.classify() in {fcInf, fcNegInf}: return Inf
if s.high <= s.low: return 0
var p = s.low
var count = 0.0
while p < s.high:
if s.predicate(p): count += 1
p += Interval
result = count * Interval
 
 
proc isEmpty(s: RealSet): bool =
if s.high == s.low: not s.predicate(s.low)
else: s.length == 0
 
 
when isMainModule:
let
a = initRealSet(0.0..1.0, LeftOpen)
b = initRealSet(0.0..2.0, RightOpen)
c = initRealSet(1.0..2.0, LeftOpen)
d = initRealSet(0.0..3.0, RightOpen)
e = initRealSet(0.0..1.0, BothOpen)
f = initRealSet(0.0..1.0, Closed)
g = initRealSet(0.0..0.0, Closed)
 
for n in 0..2:
let x = n.toFloat
echo &"{n} ∊ (0, 1] ∪ [0, 2) is {x in (a + b)}"
echo &"{n} ∊ [0, 2) ∩ (1, 2] is {x in (b * c)}"
echo &"{n} ∊ [0, 3) − (0, 1) is {x in (d - e)}"
echo &"{n} ∊ [0, 3) − [0, 1] is {x in (d - f)}\n"
 
echo &"[0, 0] is empty is {g.isEmpty()}.\n"
 
let
aa = RealSet(low: 0, high: 10,
predicate: (x: float) => 0 < x and x < 10 and abs(sin(PI * x * x)) > 0.5)
bb = RealSet(low: 0, high: 10,
predicate: (x: float) => 0 < x and x < 10 and abs(sin(PI * x)) > 0.5)
cc = aa - bb
 
echo &"Approximative length of A - B is {cc.length}."</syntaxhighlight>
 
{{out}}
<pre>0 ∊ (0, 1] ∪ [0, 2) is true
0 ∊ [0, 2) ∩ (1, 2] is false
0 ∊ [0, 3) − (0, 1) is true
0 ∊ [0, 3) − [0, 1] is false
 
1 ∊ (0, 1] ∪ [0, 2) is true
1 ∊ [0, 2) ∩ (1, 2] is false
1 ∊ [0, 3) − (0, 1) is true
1 ∊ [0, 3) − [0, 1] is false
 
2 ∊ (0, 1] ∪ [0, 2) is false
2 ∊ [0, 2) ∩ (1, 2] is false
2 ∊ [0, 3) − (0, 1) is true
2 ∊ [0, 3) − [0, 1] is true
 
[0, 0] is empty is false.
 
Approximative length of A - B is 2.07587.</pre>
 
=={{header|PARI/GP}}==
Define some sets and use built-in functions:
<syntaxhighlight lang="parigp">set11(x,a,b)=select(x -> a <= x && x <= b, x);
set01(x,a,b)=select(x -> a < x && x <= b, x);
set10(x,a,b)=select(x -> a <= x && x < b, x);
set00(x,a,b)=select(x -> a < x && x < b, x);
 
V = [0, 1, 2];
 
setunion(set01(V, 0, 1), set10(V, 0, 2))
setintersect(set10(V, 0, 2), set01(V, 1, 2))
setminus(set10(V, 0, 3), set00(V, 0, 1))
setminus(set10(V, 0, 3), set11(V, 0, 1))</syntaxhighlight>
Output:<pre>
[0, 1]
[]
[0, 1, 2]
[2]</pre>
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use utf8;
 
# numbers used as boundaries to real sets. Each has 3 components:
Line 815 ⟶ 2,525:
my $z = $x - $y;
print "A - B\t= ", brev($z), "\n\tlength = ", $z->len, "\n";
print $z ? "not empty\n" : "empty\n";</langsyntaxhighlight>output<syntaxhighlight lang="text">Set 0 = [0.00, 2.00): has 0; has 1;
Set 1 = (0.00, 2.00): has 1;
Set 2 = [0.00, 0.00] ∪ [1.00, 3.00): has 0; has 1; has 2;
Line 827 ⟶ 2,537:
A - B = [0.83, 0.91) ∪ (1.08, 1.17] ∪ ... ∪ (9.91, 9.94) ∪ (9.96, 9.99)
length = 2.07586484118467
not empty</langsyntaxhighlight>
 
=={{header|Perl 6}}==
=={{header|Phix}}==
<lang perl6>class Iv {
{{trans|Go}}
has $.range handles <min max excludes_min excludes_max minmax ACCEPTS>;
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">enum</span> <span style="color: #000000;">ID</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ARGS</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">cf</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">call_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ID</span><span style="color: #0000FF;">],</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ARGS</span><span style="color: #0000FF;">])&</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">Union</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #000000;">cf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span> <span style="color: #000000;">cf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">Inter</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #000000;">cf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #000000;">cf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">Diffr</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #000000;">cf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #008080;">not</span> <span style="color: #000000;">cf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">OpOp</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">x</span> <span style="color: #008080;">and</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">b</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">ClCl</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;"><=</span> <span style="color: #000000;">x</span> <span style="color: #008080;">and</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;"><=</span> <span style="color: #000000;">b</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">OpCl</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">x</span> <span style="color: #008080;">and</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;"><=</span> <span style="color: #000000;">b</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">ClOp</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;"><=</span> <span style="color: #000000;">x</span> <span style="color: #008080;">and</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">b</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #000080;font-style:italic;">-- expected
-- ---- desc ----, 0 1 2, --------------- set method ---------------</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"(0,1] u [0,2)"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">Union</span><span style="color: #0000FF;">,{{</span><span style="color: #000000;">OpCl</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}},{</span><span style="color: #000000;">ClOp</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">}}}}},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"[0,2) n (1,2]"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">Inter</span><span style="color: #0000FF;">,{{</span><span style="color: #000000;">ClOp</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">}},{</span><span style="color: #000000;">OpCl</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">}}}}},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"[0,3) - (0,1)"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">Diffr</span><span style="color: #0000FF;">,{{</span><span style="color: #000000;">ClOp</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">}},{</span><span style="color: #000000;">OpOp</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}}}}},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"[0,3) - [0,1]"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">Diffr</span><span style="color: #0000FF;">,{{</span><span style="color: #000000;">ClOp</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">}},{</span><span style="color: #000000;">ClCl</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}}}}}}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">desc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">expect</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">method</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">2</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">method</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">expect</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]?</span><span style="color: #008000;">"error"</span><span style="color: #0000FF;">:</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d in %s : %t %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">desc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">error</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
0 in (0,1] u [0,2) : true
1 in (0,1] u [0,2) : true
2 in (0,1] u [0,2) : false
 
0 in [0,2) n (1,2] : false
1 in [0,2) n (1,2] : false
2 in [0,2) n (1,2] : false
 
0 in [0,3) - (0,1) : true
1 in [0,3) - (0,1) : true
2 in [0,3) - (0,1) : true
 
0 in [0,3) - [0,1] : false
1 in [0,3) - [0,1] : false
2 in [0,3) - [0,1] : true
</pre>
Extra credit - also translated from Go, but with an extended loop and crude summation, inspired by Java/Kotlin.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">function</span> <span style="color: #000000;">aspxx</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">*</span><span style="color: #000000;">x</span><span style="color: #0000FF;">*</span><span style="color: #000000;">x</span><span style="color: #0000FF;">))></span><span style="color: #000000;">0.5</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">aspx</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">*</span><span style="color: #000000;">x</span><span style="color: #0000FF;">))</span> <span style="color: #0000FF;">></span><span style="color: #000000;">0.5</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">A</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">Inter</span><span style="color: #0000FF;">,{{</span><span style="color: #000000;">OpOp</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">}},{</span><span style="color: #000000;">aspxx</span><span style="color: #0000FF;">,{}}}},</span>
<span style="color: #000000;">B</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">Inter</span><span style="color: #0000FF;">,{{</span><span style="color: #000000;">OpOp</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">}},{</span><span style="color: #000000;">aspx</span><span style="color: #0000FF;">,{}}}},</span>
<span style="color: #000000;">C</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">Diffr</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">A</span><span style="color: #0000FF;">,</span><span style="color: #000000;">B</span><span style="color: #0000FF;">}}</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">step</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0.00001</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">x</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">cf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">C</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">x</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">step</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Approximate length of A-B: %.5f\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">count</span><span style="color: #0000FF;">*</span><span style="color: #000000;">step</span><span style="color: #0000FF;">})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Approximate length of A-B: 2.07587
</pre>
 
=={{header|Python}}==
<syntaxhighlight lang="python">class Setr():
def __init__(self, lo, hi, includelo=True, includehi=False):
self.eqn = "(%i<%sX<%s%i)" % (lo,
'=' if includelo else '',
'=' if includehi else '',
hi)
 
def __contains__(self, X):
return eval(self.eqn, locals())
 
# union
def __or__(self, b):
ans = Setr(0,0)
ans.eqn = "(%sor%s)" % (self.eqn, b.eqn)
return ans
 
# intersection
def __and__(self, b):
ans = Setr(0,0)
ans.eqn = "(%sand%s)" % (self.eqn, b.eqn)
return ans
 
# difference
def __sub__(self, b):
ans = Setr(0,0)
ans.eqn = "(%sand not%s)" % (self.eqn, b.eqn)
return ans
 
def __repr__(self):
return "Setr%s" % self.eqn
 
 
sets = [
Setr(0,1, 0,1) | Setr(0,2, 1,0),
Setr(0,2, 1,0) & Setr(1,2, 0,1),
Setr(0,3, 1,0) - Setr(0,1, 0,0),
Setr(0,3, 1,0) - Setr(0,1, 1,1),
]
settexts = '(0, 1] ∪ [0, 2);[0, 2) ∩ (1, 2];[0, 3) − (0, 1);[0, 3) − [0, 1]'.split(';')
 
for s,t in zip(sets, settexts):
print("Set %s %s. %s" % (t,
', '.join("%scludes %i"
% ('in' if v in s else 'ex', v)
for v in range(3)),
s.eqn))</syntaxhighlight>
 
;Output:
<pre>Set (0, 1] ∪ [0, 2) includes 0, includes 1, excludes 2. ((0<X<=1)or(0<=X<2))
Set [0, 2) ∩ (1, 2] excludes 0, excludes 1, excludes 2. ((0<=X<2)and(1<X<=2))
Set [0, 3) − (0, 1) includes 0, includes 1, includes 2. ((0<=X<3)and not(0<X<1))
Set [0, 3) − [0, 1] excludes 0, excludes 1, includes 2. ((0<=X<3)and not(0<=X<=1))
</pre>
 
=={{header|Racket}}==
This is a simple representation of sets as functions (so obviously no good way to the the extra set length).
<syntaxhighlight lang="racket">
#lang racket
 
;; Use a macro to allow infix operators
(require (only-in racket [#%app #%%app]))
(define-for-syntax infixes '())
(define-syntax (definfix stx)
(syntax-case stx ()
[(_ (x . xs) body ...) #'(definfix x (λ xs body ...))]
[(_ x body) (begin (set! infixes (cons #'x infixes)) #'(define x body))]))
(define-syntax (#%app stx)
(syntax-case stx ()
[(_ X op Y)
(and (identifier? #'op) (ormap (λ(o) (free-identifier=? #'op o)) infixes))
#'(#%%app op X Y)]
[(_ f x ...) #'(#%%app f x ...)]))
 
 
;; Ranges: (X +-+ Y) => [X,Y]; (X --- Y) => (X,Y); and same for `+--' and `--+'
;; Simple implementation as functions
 
;; Constructors
(definfix ((+-+ X Y) n) (<= X n Y)) ; [X,Y]
(definfix ((--- X Y) n) (< X n Y)) ; (X,Y)
(definfix ((+-- X Y) n) (and (<= X n) (< n Y))) ; [X,Y)
(definfix ((--+ X Y) n) (and (< X n) (<= n Y))) ; (X,Y]
(definfix ((== X) n) (= X n)) ; [X,X]
;; Set operations
(definfix ((∪ . Rs) n) (ormap (λ(p) (p n)) Rs))
(definfix ((∩ . Rs) n) (andmap (λ(p) (p n)) Rs))
(definfix ((∖ R1 R2) n) (and (R1 n) (not (R2 n)))) ; set-minus, not backslash
(define ((¬ R) n) (not (R n)))
;; Special sets
(define (∅ n) #f)
(define (ℜ n) #t)
 
(define-syntax-rule (try set)
(apply printf "~a => ~a ~a ~a\n" (~s #:width 23 'set)
(let ([pred set]) (for/list ([i 3]) (if (pred i) 'Y 'N)))))
(try ((0 --+ 1) ∪ (0 +-- 2)))
(try ((0 +-- 2) ∩ (1 --+ 2)))
(try ((0 +-- 3) ∖ (0 --- 1)))
(try ((0 +-- 3) ∖ (0 +-+ 1)))
</syntaxhighlight>
 
Output:
<pre>
((0 --+ 1) ∪ (0 +-- 2)) => Y Y N
((0 +-- 2) ∩ (1 --+ 2)) => N N N
((0 +-- 3) ∖ (0 --- 1)) => Y Y Y
((0 +-- 3) ∖ (0 +-+ 1)) => N N Y
</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2018.10}}
<syntaxhighlight lang="raku" line>class Iv {
has $.range handles <min max excludes-min excludes-max minmax ACCEPTS>;
method empty {
$.min after $.max or $.min === $.max && ($.excludes_minexcludes-min || $.excludes_maxexcludes-max)
}
multi method Bool() { not self.empty };
method length() { $.max - $.min }
method gist() {
($.excludes_minexcludes-min ?? '(' !! '[') ~
$.min ~ ',' ~ $.max ~
($.excludes_maxexcludes-max ?? ')' !! ']');
}
}
Line 853 ⟶ 2,745:
method new(@ranges) {
my @iv = canon @ranges.map: { Iv.new(:range($_)) }
self.bless(*, :intervals(@iv));
}
 
Line 863 ⟶ 2,755:
}
my $pre;
push @old, $(Inf^..Inf) unless @old[*-1].max === Inf;
if @old[0].min === -Inf {
$pre = @old.shift;
Line 872 ⟶ 2,764:
while @old {
my $old = @old.shift;
my $excludes_minexcludes-min = !$pre.excludes_maxexcludes-max;
my $excludes_maxexcludes-max = !$old.excludes_minexcludes-min;
push @new, $(Range.new($pre.max,$old.min,:$excludes_minexcludes-min,:$excludes_max)excludes-max);
$pre = $old;
}
Line 896 ⟶ 2,788:
my $min = $a.range.min max $b.range.min;
my $max = $a.range.max min $b.range.max;
my $excludes_minexcludes-min = not $min ~~ $a & $b;
my $excludes_maxexcludes-max = not $max ~~ $a & $b;
Iv.new(:range(Range.new($min,$max,:$excludes_minexcludes-min, :$excludes_maxexcludes-max)));
}
}
Line 904 ⟶ 2,796:
my $min = $a.range.min min $b.range.min;
my $max = $a.range.max max $b.range.max;
my $excludes_minexcludes-min = not $min ~~ $a | $b;
my $excludes_maxexcludes-max = not $max ~~ $a | $b;
Iv.new(:range(Range.new($min,$max,:$excludes_minexcludes-min, :$excludes_maxexcludes-max)));
}
 
Line 916 ⟶ 2,808:
my $min = $a.range.min max $b.range.min;
my $max = $a.range.max min $b.range.max;
my $excludes_minexcludes-min = not $min ~~ $a & $b;
my $excludes_maxexcludes-max = not $max ~~ $a & $b;
push @overlap, $(Range.new($min,$max,:$excludes_minexcludes-min, :$excludes_max)excludes-max);
}
}
Line 952 ⟶ 2,844:
 
say "\t\t\t\t0\t1\t2";
say "(0, 1] ∪ [0, 2) -> $s1.gist()\t", 0 ~~ $s1,"\t", 1 ~~ $s1,"\t", 2 ~~ $s1;
say "[0, 2) ∩ (1, 2] -> $s2.gist()\t", 0 ~~ $s2,"\t", 1 ~~ $s2,"\t", 2 ~~ $s2;
say "[0, 3) − (0, 1) -> $s3.gist()\t", 0 ~~ $s3,"\t", 1 ~~ $s3,"\t", 2 ~~ $s3;
say "[0, 3) − [0, 1] -> $s4.gist()\t", 0 ~~ $s4,"\t", 1 ~~ $s4,"\t", 2 ~~ $s4;
 
say '';
Line 962 ⟶ 2,854:
say "[0,3] − ℝ is empty: ", not iv(0..3) − ℝ;
 
my $A = iv(0..10)
iv |(0..10).map({ $_ - 1/6 .. $_ + 1/6 }).cache;
[∪] (0..10).map: { iv $_ - 1/6 .. $_ + 1/6 }
 
my $B = iv 0..sqrt(1/6),
|(1..99).map({ $(sqrt($_-1/6) .. sqrt($_ + 1/6)) }), sqrt(100-1/6)..10;
sqrt(100-1/6)..10;
 
say 'A − A is empty: ', not $A − $A;
Line 977 ⟶ 2,867:
say "A − B =";
say " ",.gist for $C.intervals;
say "Length A − B = ", $C.length;</langsyntaxhighlight>
{{out}}
<pre> 0 1 2
Line 1,032 ⟶ 2,922:
Length A − B = 2.07586484118467</pre>
 
=={{header|PythonREXX}}==
===no error checking, no ∞===
<lang python>class Setr():
<syntaxhighlight lang="rexx">/*REXX program demonstrates a way to represent any set of real numbers and usage. */
def __init__(self, lo, hi, includelo=True, includehi=False):
call quertySet 1, 3, '[1,2)'
self.eqn = "(%i<%sX<%s%i)" % (lo,
call quertySet , , '[0,2) union (1,3)'
'=' if includelo else '',
call quertySet , , '[0,1) union (2,3]'
'=' if includehi else '',
call quertySet , , '[0,2] inter hi(1,3)'
call quertySet , , '(1,2) ∩ (2,3]'
call quertySet , , '[0,2) \ (1,3)'
say; say center(' start of required tasks ', 40, "═")
call quertySet , , '(0,1] union [0,2)'
call quertySet , , '[0,2) ∩ (1,3)'
call quertySet , , '[0,3] - (0,1)'
call quertySet , , '[0,3] - [0,1]'
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
emptySet: parse arg _; nam= valSet(_, 00); return @.3>@.4
/*──────────────────────────────────────────────────────────────────────────────────────*/
isInSet: parse arg #,x; call valSet x
if \datatype(#, 'N') then call set_bad "number isn't not numeric:" #
if (@.1=='(' & #<=@.2) |,
(@.1=='[' & #< @.2) |,
(@.4==')' & #>=@.3) |,
(@.4==']' & #> @.3) then return 0
return 1
/*──────────────────────────────────────────────────────────────────────────────────────*/
quertySet: parse arg lv,hv,s1 oop s2 .; op=oop; upper op; cop=
if lv=='' then lv=0; if hv=="" then hv= 2; if op=='' then cop= 0
if wordpos(op, '| or UNION') \==0 then cop= "|"
if wordpos(op, '& ∩ AND INTER INTERSECTION') \==0 then cop= "&"
if wordpos(op, '\ - DIF DIFF DIFFERENCE') \==0 then cop= "\"
say
do i=lv to hv; b = isInSet(i, s1)
if cop\==0 then do
b2= isInSet(i, s2)
if cop=='&' then b= b & b2
if cop=='|' then b= b | b2
if cop=='\' then b= b & \b2
end
express = s1 center(oop, max(5, length(oop) ) ) s2
say right(i, 5) ' is in set' express": " word('no yes', b+1)
end /*i*/
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
valSet: parse arg q; q=space(q, 0); L=length(q); @.0= ','; @.4= right(q,1)
parse var q @.1 2 @.2 ',' @.3 (@.4)
if @.2>@.3 then parse var L . @.0 @.2 @.3
return space(@.1 @.2 @.0 @.3 @.4, 0)</syntaxhighlight>
{{out|output|text=&nbsp; is the same as the next REXX version (below).}}
 
===has error checking, ∞ support===
def __contains__(self, X):
<syntaxhighlight lang="rexx">/*REXX program demonstrates a way to represent any set of real numbers and usage. */
return eval(self.eqn, locals())
call quertySet 1, 3, '[1,2)'
call quertySet , , '[0,2) union (1,3)'
call quertySet , , '[0,1) union (2,3]'
call quertySet , , '[0,2] inter (1,3)'
call quertySet , , '(1,2) ∩ (2,3]'
call quertySet , , '[0,2) \ (1,3)'
say; say center(' start of required tasks ', 40, "═")
call quertySet , , '(0,1] union [0,2)'
call quertySet , , '[0,2) ∩ (1,3)'
call quertySet , , '[0,3] - (0,1)'
call quertySet , , '[0,3] - [0,1]'
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
badSet: say; say '***error*** bad format of SET_def: ('arg(1)")"; exit
/*──────────────────────────────────────────────────────────────────────────────────────*/
emptySet: parse arg _; nam= valSet(_, 00); return @.3>@.4
/*──────────────────────────────────────────────────────────────────────────────────────*/
isInSet: parse arg #,x; call valSet x
if \datatype(#, 'N') then call set_bad "number isn't not numeric:" #
if (@.1=='(' & #<=@.2) |,
(@.1=='[' & #< @.2) |,
(@.4==')' & #>=@.3) |,
(@.4==']' & #> @.3) then return 0
return 1
/*──────────────────────────────────────────────────────────────────────────────────────*/
quertySet: parse arg lv,hv,s1 oop s2 .; op=oop; upper op; cop=
if lv=='' then lv=0; if hv=="" then hv= 2; if op=='' then cop= 0
if wordpos(op, '| or UNION') \==0 then cop= "|"
if wordpos(op, '& ∩ AND INTER INTERSECTION') \==0 then cop= "&"
if wordpos(op, '\ - DIF DIFF DIFFERENCE') \==0 then cop= "\"
say
do i=lv to hv; b = isInSet(i, s1)
if cop\==0 then do
b2= isInSet(i, s2)
if cop=='&' then b= b & b2
if cop=='|' then b= b | b2
if cop=='\' then b= b & \b2
end
express = s1 center(oop, max(5, length(oop) ) ) s2
say right(i, 5) ' is in set' express": " word('no yes', b+1)
end /*i*/
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
valSet: parse arg q; q=space(q, 0); L= length(q); @.0= ','
infinity = copies(9, digits() - 1)'e'copies(9, digits() - 1)0
if L<2 then call set_bad 'invalid expression'
@.4= right(q, 1)
parse var q @.1 2 @.2 ',' @.3 (@.4)
if @.1\=='(' & @.1\=="[" then call set_bad 'left boundry'
if @.4\==')' & @.4\=="]" then call set_bad 'right boundry'
do j=2 to 3; u=@.j; upper u
if right(@.j, 1)=='∞' | u="INFINITY" then @.j= '-'infinity
if \datatype(@.j, 'N') then call set_bad "value not numeric:" @.j
end /*j*/
if @.2>@.3 then parse var L . @.0 @.2 @.3
return space(@.1 @.2 @.0 @.3 @.4, 0)</syntaxhighlight>
{{out|output|text=&nbsp; when using the (internal) default inputs:}}
<pre>
1 is in set [1,2) : yes
2 is in set [1,2) : no
3 is in set [1,2) : no
 
#0 is in set [0,2) union (1,3): yes
def1 __or__(self is in set [0,2) bunion (1,3): yes
2 is in ansset =[0,2) union Setr(01,03): yes
ans.eqn = "(%sor%s)" % (self.eqn, b.eqn)
return ans
 
0 is in set [0,1) union (2,3]: yes
# intersection
1 is in set [0,1) union (2,3]: no
def __and__(self, b):
2 is in ansset = Setr([0,01) union (2,3]: no
ans.eqn = "(%sand%s)" % (self.eqn, b.eqn)
return ans
 
0 is in set [0,2] inter (1,3): no
# difference
def1 __sub__(self is in set [0,2] binter (1,3): no
2 is in ansset =[0,2] inter Setr(01,03): yes
ans.eqn = "(%sand not%s)" % (self.eqn, b.eqn)
return ans
 
0 is in set (1,2) ∩ (2,3]: no
def __repr__(self):
1 is in returnset "Setr%s"(1,2) % self.eqn ∩ (2,3]: no
2 is in set (1,2) ∩ (2,3]: no
 
0 is in set [0,2) \ (1,3): yes
1 is in set [0,2) \ (1,3): yes
2 is in set [0,2) \ (1,3): no
 
═══════ start of required tasks ════════
sets = [
Setr(0,1, 0,1) | Setr(0,2, 1,0),
Setr(0,2, 1,0) & Setr(1,2, 0,1),
Setr(0,3, 1,0) - Setr(0,1, 0,0),
Setr(0,3, 1,0) - Setr(0,1, 1,1),
]
settexts = '(0, 1] ∪ [0, 2);[0, 2) ∩ (1, 2];[0, 3) − (0, 1);[0, 3) − [0, 1]'.split(';')
 
for s,t in zip(sets, settexts):
print("Set %s %s. %s" % (t,
', '.join("%scludes %i"
% ('in' if v in s else 'ex', v)
for v in range(3)),
s.eqn))</lang>
 
;Output:
<pre>Set (0, 1] ∪ [0, 2) includes 0, includes 1, excludes 2. ((0<X<=1)or(0<=X<2))
Set [0, 2) ∩ (1, 2] excludes 0, excludes 1, excludes 2. ((0<=X<2)and(1<X<=2))
Set [0, 3) − (0, 1) includes 0, includes 1, includes 2. ((0<=X<3)and not(0<X<1))
Set [0, 3) − [0, 1] excludes 0, excludes 1, includes 2. ((0<=X<3)and not(0<=X<=1))
</pre>
 
=={{header|Racket}}==
This is a simple representation of sets as functions (so obviously no good way to the the extra set length).
<lang Racket>
#lang racket
 
;; Use a macro to allow infix operators
(require (only-in racket [#%app #%%app]))
(define-for-syntax infixes '())
(define-syntax (definfix stx)
(syntax-case stx ()
[(_ (x . xs) body ...) #'(definfix x (λ xs body ...))]
[(_ x body) (begin (set! infixes (cons #'x infixes)) #'(define x body))]))
(define-syntax (#%app stx)
(syntax-case stx ()
[(_ X op Y)
(and (identifier? #'op) (ormap (λ(o) (free-identifier=? #'op o)) infixes))
#'(#%%app op X Y)]
[(_ f x ...) #'(#%%app f x ...)]))
 
 
;; Ranges: (X +-+ Y) => [X,Y]; (X --- Y) => (X,Y); and same for `+--' and `--+'
;; Simple implementation as functions
 
;; Constructors
(definfix ((+-+ X Y) n) (<= X n Y)) ; [X,Y]
(definfix ((--- X Y) n) (< X n Y)) ; (X,Y)
(definfix ((+-- X Y) n) (and (<= X n) (< n Y))) ; [X,Y)
(definfix ((--+ X Y) n) (and (< X n) (<= n Y))) ; (X,Y]
(definfix ((== X) n) (= X n)) ; [X,X]
;; Set operations
(definfix ((∪ . Rs) n) (ormap (λ(p) (p n)) Rs))
(definfix ((∩ . Rs) n) (andmap (λ(p) (p n)) Rs))
(definfix ((∖ R1 R2) n) (and (R1 n) (not (R2 n)))) ; set-minus, not backslash
(define ((¬ R) n) (not (R n)))
;; Special sets
(define (∅ n) #f)
(define (ℜ n) #t)
 
(define-syntax-rule (try set)
(apply printf "~a => ~a ~a ~a\n" (~s #:width 23 'set)
(let ([pred set]) (for/list ([i 3]) (if (pred i) 'Y 'N)))))
(try ((0 --+ 1) ∪ (0 +-- 2)))
(try ((0 +-- 2) ∩ (1 --+ 2)))
(try ((0 +-- 3) ∖ (0 --- 1)))
(try ((0 +-- 3) ∖ (0 +-+ 1)))
</lang>
 
Output:
<pre>
((0 --+ 1) ∪ (0 +-- 2)) => Y Y N
((0 +-- 2) ∩ (1 --+ 2)) => N N N
((0 +-- 3) ∖ (0 --- 1)) => Y Y Y
((0 +-- 3) ∖ (0 +-+ 1)) => N N Y
</pre>
 
=={{header|REXX}}==
===no error checking, no ∞===
<lang rexx>/*REXX pgm demonstrates a way to represent any set of real #s and usage.*/
call set_query , , '(0,1] union [0,2)'
call set_query , , '[0,2) ∩ (1,3)'
call set_query , , '[0,3] - (0,1)'
call set_query , , '[0,3] - [0,1]'
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────SET_empty subroutine────────────────*/
set_empty: parse arg _; nam=set_val(_,00); return @.3>@.4
/*──────────────────────────────────SET_ISIN subroutine─────────────────*/
set_isin: parse arg #,x; call set_val x
if \datatype(#,'N') then call set_bad "number isn't not numeric:" #
if (@.1=='(' & #<=@.2) |,
(@.1=='[' & #< @.2) |,
(@.4==')' & #>=@.3) |,
(@.4==']' & #> @.3) then return 0
return 1
/*──────────────────────────────────SET_query subroutine────────────────*/
set_query: parse arg lv,hv,s1 oop s2 .; op=oop; upper op; cop=
if lv=='' then lv=0; if hv=='' then hv=2; if op=='' then cop=0
if wordpos(op,'| or UNION') \==0 then cop='|'
if wordpos(op,'& ∩ AND INTER INTERSECTION') \==0 then cop='&'
if wordpos(op,'\ - DIF DIFF DIFFERENCE') \==0 then cop='\'
say
do i=lv to hv; b =set_isin(i,s1)
if cop\==0 then do
b2=set_isin(i,s2)
if cop=='&' then b=b & b2
if cop=='|' then b=b | b2
if cop=='\' then b=b & \b2
end
express = s1 center(oop,max(5,length(oop))) s2
say right(i,5) ' is in set' express": " word('no yes',b+1)
end /*i*/
return
/*──────────────────────────────────SET_VAL subroutine──────────────────*/
set_val: parse arg q; q=space(q,0); L=length(q); @.0=','
@.4=right(q,1)
parse var q @.1 2 @.2 ',' @.3 (@.4)
if @.2>@.3 then parse var L . @.0 @.2 @.3
return space(@.1 @.2 @.0 @.3 @.4,0)</lang>
'''output''' is the same as version 2
 
===has error checking, ∞ support===
<lang rexx>/*REXX pgm demonstrates a way to represent any set of real #s and usage.*/
call set_query , , '(0,1] union [0,2)'
call set_query , , '[0,2) ∩ (1,3)'
call set_query , , '[0,3] - (0,1)'
call set_query , , '[0,3] - [0,1]'
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────SET_BAD subroutine─────────-────────*/
set_bad: say; say '***error!*** bad format of SET_def: ('arg(1)")"; exit
/*──────────────────────────────────SET_empty subroutine────────────────*/
set_empty: parse arg _; nam=set_val(_,00); return @.3>@.4
/*──────────────────────────────────SET_ISIN subroutine─────────────────*/
set_isin: parse arg #,x; call set_val x
if \datatype(#,'N') then call set_bad "number isn't not numeric:" #
if (@.1=='(' & #<=@.2) |,
(@.1=='[' & #< @.2) |,
(@.4==')' & #>=@.3) |,
(@.4==']' & #> @.3) then return 0
return 1
/*──────────────────────────────────SET_query subroutine────────────────*/
set_query: parse arg lv,hv,s1 oop s2 .; op=oop; upper op; cop=
if lv=='' then lv=0; if hv=='' then hv=2; if op=='' then cop=0
if wordpos(op,'| or UNION') \==0 then cop='|'
if wordpos(op,'& ∩ AND INTER INTERSECTION') \==0 then cop='&'
if wordpos(op,'\ - DIF DIFF DIFFERENCE') \==0 then cop='\'
if cop=='' then call set_bad 'invalid operation:' oop
say
do i=lv to hv; b =set_isin(i,s1)
if cop\==0 then do
b2=set_isin(i,s2)
if cop=='&' then b=b & b2
if cop=='|' then b=b | b2
if cop=='\' then b=b & \b2
end
express = s1 center(oop,max(5,length(oop))) s2
say right(i,5) ' is in set' express": " word('no yes',b+1)
end /*i*/
return
/*──────────────────────────────────SET_VAL subroutine──────────────────*/
set_val: parse arg q; q=space(q,0); L=length(q); @.0=','
infinity = copies(9,digits()-1)'e'copies(9,digits()-1)'0'
if L<2 then call set_bad 'invalid expression'
@.4=right(q,1)
parse var q @.1 2 @.2 ',' @.3 (@.4)
if @.1\=='(' & @.1\=='[' then call set_bad 'left boundry'
if @.4\==')' & @.4\==']' then call set_bad 'right boundry'
 
do j=2 to 3; u=@.j; upper u
if right(@.j,1)=='∞' | u="INFINITY" then @.j='-'infinity
if \datatype(@.j,'N') then call set_bad 'value not numeric:' @.j
end /*j*/
 
if @.2>@.3 then parse var L . @.0 @.2 @.3
return space(@.1 @.2 @.0 @.3 @.4,0)</lang>
'''output'''
<pre style="overflow:scroll">
0 is in set (0,1] union [0,2): yes
1 is in set (0,1] union [0,2): yes
Line 1,261 ⟶ 3,077:
=={{header|Ruby}}==
{{works with|Ruby|1.9.3}}
<langsyntaxhighlight lang="ruby">class Rset
Set = Struct.new(:lo, :hi, :inc_lo, :inc_hi) do
def include?(x)
Line 1,431 ⟶ 3,247:
def Rset(lo, hi, inc_hi=false)
Rset.new(lo, hi, false, inc_hi)
end</langsyntaxhighlight>
 
Test case:
<langsyntaxhighlight lang="ruby">p a = Rset[1,2,false]
[1,2,3].each{|x|puts "#{x} => #{a.include?(x)}"}
puts
Line 1,478 ⟶ 3,294:
puts "a = #{a = Rset(-inf,inf)}"
puts "b = #{b = Rset.parse('[1/3,11/7)')}"
puts "a - b -> #{a - b}"</langsyntaxhighlight>
 
{{out}}
Line 1,533 ⟶ 3,349:
{{works with|Ruby|2.1+}}
(with Rational suffix.)
<langsyntaxhighlight lang="ruby">str, e = "e = Rset.new", nil
puts "#{str} -> #{eval(str)}\t\t# create empty set"
str = "e.empty?"
Line 1,563 ⟶ 3,379:
puts "b.length : #{b.length}"
puts "a - b : #{a - b}"
puts "(a-b).length : #{(a-b).length}"</langsyntaxhighlight>
 
{{out}}
Line 1,577 ⟶ 3,393:
(a-b).length : 2.0758648411846745
</pre>
=={{header|Rust}}==
This implementation defines a <code>RealSet</code> as either:
* A <code>RangeSet</code>, which contains all numbers from a start to an end, inclusive, or exclusive. When the <code>contains()</code> method is called on a range set, it will return whether a number is between its bounds.
* A <code>CompositeSet</code> which represents a <code>SetOperation</code> (union, intersection, or difference) between two other <code>RealSet</code>s, which themselves can be composite or not. When the <code>contains()</code> method is called on a composite set for a given number, it will recursively call contains() on its component sets to check whether they contain the number. Depending on the operation, this will define whether the number is contained in this set.
Since we use Rust's [https://doc.rust-lang.org/std/primitive.f64.html f64], which is a standard [https://en.wikipedia.org/wiki/IEEE_754 IEEE 754] double-precision floating-point number, we get correct behavior at infinity for free.
<syntaxhighlight lang="rust">#[derive(Debug)]
enum SetOperation {
Union,
Intersection,
Difference,
}
 
#[derive(Debug, PartialEq)]
enum RangeType {
Inclusive,
Exclusive,
}
 
#[derive(Debug)]
struct CompositeSet<'a> {
operation: SetOperation,
a: &'a RealSet<'a>,
b: &'a RealSet<'a>,
}
 
#[derive(Debug)]
struct RangeSet {
range_types: (RangeType, RangeType),
start: f64,
end: f64,
}
 
#[derive(Debug)]
enum RealSet<'a> {
RangeSet(RangeSet),
CompositeSet(CompositeSet<'a>),
}
 
impl RangeSet {
fn compare_start(&self, n: f64) -> bool {
if self.range_types.0 == RangeType::Inclusive {
self.start <= n
} else {
self.start < n
}
}
 
fn compare_end(&self, n: f64) -> bool {
if self.range_types.1 == RangeType::Inclusive {
n <= self.end
} else {
n < self.end
}
}
}
 
impl<'a> RealSet<'a> {
fn new(start_type: RangeType, start: f64, end: f64, end_type: RangeType) -> Self {
RealSet::RangeSet(RangeSet {
range_types: (start_type, end_type),
start,
end,
})
}
 
fn operation(&'a self, other: &'a Self, operation: SetOperation) -> Self {
RealSet::CompositeSet(CompositeSet {
operation,
a: self,
b: other,
})
}
 
fn union(&'a self, other: &'a Self) -> Self {
self.operation(other, SetOperation::Union)
}
 
fn intersection(&'a self, other: &'a Self) -> Self {
self.operation(other, SetOperation::Intersection)
}
 
fn difference(&'a self, other: &'a Self) -> Self {
self.operation(other, SetOperation::Difference)
}
 
fn contains(&self, n: f64) -> bool {
if let RealSet::RangeSet(range) = self {
range.compare_start(n) && range.compare_end(n)
} else if let RealSet::CompositeSet(range) = self {
match range.operation {
SetOperation::Union => range.a.contains(n) || range.b.contains(n),
SetOperation::Intersection => range.a.contains(n) && range.b.contains(n),
SetOperation::Difference => range.a.contains(n) && !range.b.contains(n),
}
} else {
unimplemented!();
}
}
}
 
fn make_contains_phrase(does_contain: bool) -> &'static str {
if does_contain {
"contains"
} else {
"does not contain"
}
}
 
use RangeType::*;
 
fn main() {
for (set_name, set) in [
(
"(0, 1] ∪ [0, 2)",
RealSet::new(Exclusive, 0.0, 1.0, Inclusive)
.union(&RealSet::new(Inclusive, 0.0, 2.0, Exclusive)),
),
(
"[0, 2) ∩ (1, 2]",
RealSet::new(Inclusive, 0.0, 2.0, Exclusive)
.intersection(&RealSet::new(Exclusive, 1.0, 2.0, Inclusive)),
),
(
"[0, 3) − (0, 1)",
RealSet::new(Inclusive, 0.0, 3.0, Exclusive)
.difference(&RealSet::new(Exclusive, 0.0, 1.0, Exclusive)),
),
(
"[0, 3) − [0, 1]",
RealSet::new(Inclusive, 0.0, 3.0, Exclusive)
.difference(&RealSet::new(Inclusive, 0.0, 1.0, Inclusive)),
),
] {
println!("Set {}", set_name);
 
for i in [0.0, 1.0, 2.0] {
println!("- {} {}", make_contains_phrase(set.contains(i)), i);
}
}
}</syntaxhighlight>
<pre>Set (0, 1] ∪ [0, 2)
- contains 0
- contains 1
- does not contain 2
Set [0, 2) ∩ (1, 2]
- does not contain 0
- does not contain 1
- does not contain 2
Set [0, 3) − (0, 1)
- contains 0
- contains 1
- contains 2
Set [0, 3) − [0, 1]
- does not contain 0
- does not contain 1
- contains 2</pre>
 
=={{header|Tcl}}==
This code represents each set of real numbers as a collection of ranges, where each range is quad of the two boundary values and whether each of those boundaries is a closed boundary. (Using expressions internally would make the code much shorter, at the cost of being much less tractable when it comes to deriving information like the length of the real line “covered” by the set.) A side-effect of the representation is that the length of the list that represents the set is, after normalization, the number of discrete ranges in the set.
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
 
proc inRange {x range} {
Line 1,725 ⟶ 3,697:
}
return $len
}</langsyntaxhighlight>
Basic problems:
<langsyntaxhighlight lang="tcl">foreach {str Set} {
{(0, 1] ∪ [0, 2)} {
union [realset {(0,1]}] [realset {[0,2)}]
Line 1,745 ⟶ 3,717:
puts "$x : $str :\t[elementOf $x $Set]"
}
}</langsyntaxhighlight>
Extra credit:
<langsyntaxhighlight lang="tcl">proc spi2 {from to} {
for {set i $from} {$i<=$to} {incr i} {
lappend result [list [expr {$i+1./6}] 0 [expr {$i+5./6}] 0]
Line 1,765 ⟶ 3,737:
set B [spi2 0 10]
set AB [difference $A $B]
puts "[llength $AB] contiguous subsets, total length [length $AB]"</langsyntaxhighlight>
Output:
<pre>
Line 1,781 ⟶ 3,753:
2 : [0, 3) − [0, 1] : 1
40 contiguous subsets, total length 2.075864841184667
</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-dynamic}}
<syntaxhighlight lang="wren">import "./dynamic" for Enum
 
var RangeType = Enum.create("RangeType", ["CLOSED", "BOTH_OPEN", "LEFT_OPEN", "RIGHT_OPEN"])
 
class RealSet {
construct new(start, end, pred) {
_low = start
_high = end
_pred = (pred == RangeType.CLOSED) ? Fn.new { |d| d >= _low && d <= _high } :
(pred == RangeType.BOTH_OPEN) ? Fn.new { |d| d > _low && d < _high } :
(pred == RangeType.LEFT_OPEN) ? Fn.new { |d| d > _low && d <= _high } :
(pred == RangeType.RIGHT_OPEN) ? Fn.new { |d| d >= _low && d < _high } : pred
}
 
low { _low }
high { _high }
pred { _pred }
 
contains(d) { _pred.call(d) }
 
union(other) {
if (!other.type == RealSet) Fiber.abort("Argument must be a RealSet")
var low2 = _low.min(other.low)
var high2 = _high.max(other.high)
return RealSet.new(low2, high2) { |d| _pred.call(d) || other.pred.call(d) }
}
 
intersect(other) {
if (!other.type == RealSet) Fiber.abort("Argument must be a RealSet")
var low2 = _low.max(other.low)
var high2 = _high.min(other.high)
return RealSet.new(low2, high2) { |d| _pred.call(d) && other.pred.call(d) }
}
 
subtract(other) {
if (!other.type == RealSet) Fiber.abort("Argument must be a RealSet")
return RealSet.new(_low, _high) { |d| _pred.call(d) && !other.pred.call(d) }
}
 
length {
if (_low.isInfinity || _high.isInfinity) return -1 // error value
if (_high <= _low) return 0
var p = _low
var count = 0
var interval = 0.00001
while (true) {
if (_pred.call(p)) count = count + 1
p = p + interval
if (p >= _high) break
}
return count * interval
}
 
isEmpty { (_high == _low) ? !_pred.call(_low) : length == 0 }
}
 
var a = RealSet.new(0, 1, RangeType.LEFT_OPEN)
var b = RealSet.new(0, 2, RangeType.RIGHT_OPEN)
var c = RealSet.new(1, 2, RangeType.LEFT_OPEN)
var d = RealSet.new(0, 3, RangeType.RIGHT_OPEN)
var e = RealSet.new(0, 1, RangeType.BOTH_OPEN)
var f = RealSet.new(0, 1, RangeType.CLOSED)
var g = RealSet.new(0, 0, RangeType.CLOSED)
 
for (i in 0..2) {
System.print("(0, 1] ∪ [0, 2) contains %(i) is %(a.union(b).contains(i))")
System.print("[0, 2) ∩ (1, 2] contains %(i) is %(b.intersect(c).contains(i))")
System.print("[0, 3) − (0, 1) contains %(i) is %(d.subtract(e).contains(i))")
System.print("[0, 3) − [0, 1] contains %(i) is %(d.subtract(f).contains(i))\n")
}
 
System.print("[0, 0] is empty is %(g.isEmpty)\n")
 
var aa = RealSet.new(0, 10) { |x| (0 < x && x < 10) && ((Num.pi * x * x).sin.abs > 0.5) }
var bb = RealSet.new(0, 10) { |x| (0 < x && x < 10) && ((Num.pi * x).sin.abs > 0.5) }
var cc = aa.subtract(bb)
System.print("Approx length of A - B is %(cc.length)")</syntaxhighlight>
 
{{out}}
<pre>
(0, 1] ∪ [0, 2) contains 0 is true
[0, 2) ∩ (1, 2] contains 0 is false
[0, 3) − (0, 1) contains 0 is true
[0, 3) − [0, 1] contains 0 is false
 
(0, 1] ∪ [0, 2) contains 1 is true
[0, 2) ∩ (1, 2] contains 1 is false
[0, 3) − (0, 1) contains 1 is true
[0, 3) − [0, 1] contains 1 is false
 
(0, 1] ∪ [0, 2) contains 2 is false
[0, 2) ∩ (1, 2] contains 2 is false
[0, 3) − (0, 1) contains 2 is true
[0, 3) − [0, 1] contains 2 is true
 
[0, 0] is empty is false
 
Approx length of A - B is 2.07587
</pre>
 
Line 1,786 ⟶ 3,861:
{{trans|D}}
No ∞
<langsyntaxhighlight lang="zkl">class RealSet{
fcn init(fx){ var [const] contains=fx; }
fcn holds(x){ contains(x) }
Line 1,792 ⟶ 3,867:
fcn __opSub(rs){ RealSet('wrap(x){ contains(x) and not rs.contains(x) }) }
fcn intersection(rs) { RealSet('wrap(x){ contains(x) and rs.contains(x) }) }
}</langsyntaxhighlight>
The python method could used but the zkl compiler is slow when used in code to generate code.
 
The method used is a bit inefficient because it closes the contains function of the other set so you can build quite a long call chain as you create new sets.
<langsyntaxhighlight lang="zkl">tester := TheVault.Test.UnitTester.UnitTester();
 
// test union
Line 1,824 ⟶ 3,899:
tester.testRun(s.holds(0.0),Void,False,__LINE__);
tester.testRun(s.holds(1.0),Void,False,__LINE__);
tester.testRun(s.holds(2.0),Void,False,__LINE__);</langsyntaxhighlight>
{{out}}
<pre>
Line 1,839 ⟶ 3,914:
</pre>
 
{{omit from|Free Pascal}}
 
{{omit from|Lilypond}}
{{omit form|Pascal|the base type of sets has to be an ordinal type}}
{{omit from|TPP}}
 
2,130

edits