summaryrefslogtreecommitdiff
path: root/miralib/ex/set.m
blob: c6a52f9734380751450a9b66b97cbf649187aa39 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
||definition of finite sets as an abstract data type, say
||	%include <ex/set>
||to include this in one of your own scripts.

abstype set *
with  makeset::[*]->set * ||converts list to set
      enum::set *->[*] ||converts set to list
      empty::set * ||empty set
      mem::set *->*->bool ||does set contain element?
      pincludes,includes::set *->set *->bool ||(proper) set inclusion
      union::[set *]->set * ||union of a list of sets
      intersect::[set *]->set * ||intersection of a list of sets
      setdiff::set *->set *->set * ||set difference of two sets
      union2::set *->set *->set * ||union of two sets
      intersect2::set *->set *->set * ||intersection of two sets
      add1::*->set *->set * ||add a single element to a set
      sub1::*->set *->set * ||remove an element from a set (if present)
      pick::set *->* ||pick some element from a set
      rest::set *->set * ||remainder of set, without element got by pick
      showset::(*->[char])->set *->[char]  ||to make sets printable

set * == [*]        ||a set is represented as a list without duplicates
makeset = uniq.sort ||for efficiency the lists are kept sorted
enum = id
empty = []
mem (a:x) b = a=b \/ a<b & mem x b
mem [] b = False
includes x y = (setdiff y x = [])
pincludes x y = x~=y & (setdiff y x = [])
union2 x y = uniq(merge x y)
union = foldr union2 empty
setdiff (a:x) (b:y) = a:setdiff x (b:y), if a<b
                    = setdiff (a:x) y, if a>b
		    = setdiff x y, otherwise
setdiff x y = x
intersect2 (a:x) (b:y) = intersect2 x (b:y), if a<b
                       = intersect2 (a:x) y, if a>b
                       = a : intersect2 x y, otherwise
intersect2 x y = []
intersect = foldl1 intersect2
add1 a (b:x) = a:b:x, if a<b
             = b:x, if a=b
             = b:add1 a x, otherwise
add1 a [] = [a]
sub1 a (b:x) = b:x, if a<b
             = x, if a=b
             = b:sub1 a x, otherwise
sub1 a [] = []
pick (a:x) = a
pick [] = error "pick empty"
rest (a:x) = x
rest [] = error "pick empty"
showset f [] = "{}"
showset f (a:x) = "{"++f a++concat(map g x)++"}"
                  where
                  g a = ',':f a

%export -uniq
||we have used the following auxiliary function, which removes adjacent
||duplicates from a list  (this is not exported from the script)
uniq::[*]->[*]
uniq (a:b:x) = uniq (a:x), if a=b
             = a:uniq (b:x), otherwise
uniq x = x