(* Class: Set Package: com.waysysweb Author: W. Shaffer Date: 27-Oct-2005 Description: This structure Maintenance: Date Author Description ----------- ------ ----------------------------------------------------------- 27-Oct-2005 Shaffer File created *) structure SET = struct (*============ Exceptions ==============================================*) exception SetException of string; (*============ Imports =============================================*) (*============ Types =============================================*) type ''a Set = ''a list; (*============ Constants ==============================================*) val empty = []; (*============ Properties ==============================================*) (*============ Attributes =============================================*) (*============ Invariant =============================================*) (*============ Initialization ==========================================*) (*============ Operations =============================================*) (* return true if set is empty *) (* Precondition: true *) (* Postcondition: set = empty *) fun isEmpty(set : ''a Set) : bool = if set = empty then true else false; (* return true if item is in set *) (* Precondition: true *) (* Postcondition: if set = empty then false *) (* else if item = hd(set) then true *) (* else item inset tl(set) *) infix inset; fun ((item : ''a) inset (set : ''a Set) ) : bool = if isEmpty(set) then false else if item = hd(set) then true else item inset tl(set); (* turn true if an item is not in the set *) (* Precondition: item : 'a andalso set : 'a Set *) (* Postcondition: not (item inset set) *) infix notinset; fun ((item : ''a) notinset (set : ''a Set)) : bool = not (item inset set); (* return a set with an item added to it *) (* Precondition: not (item inset set) *) (* Postcondition: set' = add(set, item) andalso item inset set' *) fun add(set : ''a Set, item : ''a) : ''a Set = if item inset set then raise SetException("add: item is already in set") else item::set; (* return a set with an item removed *) (* Precondition: item inset set *) (* Postcondition: remove(set, item) = set' andalso *) (* not (item inset set) *) fun remove(set : ''a Set, item : ''a) : ''a Set = if item inset set then let val first = hd(set) in if item = first then tl(set) else first::remove(set, item) end else raise SetException("remove: item is not in set"); (* return true if if each element in a set satisfies the predicate *) (* Precondition: true *) (* Postcondition: for all x inset set | pred(x) *) fun forall(set : ''a Set, pred : ''a -> bool) : bool = if set = empty then true else pred(hd(set)) andalso forall(tl(set), pred); (* return true if there exists an element that satisfies the predicate *) (* Precondition: true *) (* Postcondition: there exists x inset set | pred(x) *) fun exists(set : ''a Set, pred : ''a -> bool) : bool = if set = empty then false else if pred(hd(set)) then true else exists(tl(set), pred); (* return the cardinality of the set or the number of items in set *) (* Precondition: true *) (* Postcondition: size(empty) andalso *) (* size(add(set, item)) = size(set) + 1 *) fun card(set : '' Set) : int = length(set); (* return a set of the elements in a list *) (* Precondition: true *) (* Postcondition: set = toSet(list') andalso *) (* forall x in list1 | x inset set andalso *) (* forall(set, fn x : x in list) *) fun toSet([] ) : ''a Set = empty | toSet(item::list' : ''a list) : ''a Set = let val set = toSet(list') in if item inset set then set else add(set, item) end; (* return one element of a set *) (* Precondition: card(set) > 0 *) (* Postcondition: item = fetch(set) andalso item inset set *) fun fetch(set : ''a Set) : ''a = hd(set); (* return the union of two sets *) (* Precondition: true *) (* Postcondition: set' = union(set1, set2) andalso *) (* forall(set1, fn x => x inset set') *) (* forall(set2, fn x => x inset set') *) (* forall(set', *) (* fn x => (x inset set1) orelse (x inset set2) *) fun union(set1 : ''a Set, set2 : ''a Set) : ''a Set = if set1 = empty then set2 else let val item = fetch(set1); val set1' = remove(set1, item); val set' = union(set1', set2) in if item inset set' then set' else add(set', item) end; (* return the intersection of two sets *) (* Precondition: true *) (* Postcondition: set' = inter(set1, set2) andalso *) (* forall(set', *) (* fn x => (x inset set1) andalso (x inset set2) *) (* forall(set1, fn x => if x inset set2 then x inset set' *) (* else true) *) fun inter(set1 : ''a Set, set2 : ''a Set) : ''a Set = if set1 = empty then empty else let val item = fetch(set1); val set1' = remove(set1, item); val set' = inter(set1', set2) in if (item inset set2) andalso (not (item inset set')) then add(set', item) else set' end; (* return true if sub is a subset of superset *) (* Precondition: true *) (* Postcondition: forall(sub, fn x => x inset superset) *) fun subset(sub : ''a Set, superset : ''a Set) : bool = forall(sub, fn x => x inset superset); (* return true if a set equals another set *) (* Precondition: true *) (* Postcondition: subset(set1, set2) andalso subset(set2, set1) *) fun equals(set1 : ''a Set, set2 : ''a Set) : bool = subset(set1, set2) andalso subset(set2, set1); (* return a set of items that satisfy a predicate *) (* Precondition: true *) (* Postcondition: set' = select(set, pred) andalso *) (* subset(set', set) andalso forall(set', pred) *) fun select(set : ''a Set, pred : ''a -> bool) : ''a Set = if isEmpty(set) then empty else let val item = fetch(set); val set' = remove(set, item); val sel = select(set', pred) in if pred(item) then add(sel, item) else sel end; (* return the set after applying a function to each element *) (* Precondition: true *) (* Postcondition: set' = project(set, func) andalso *) (* forall(set, fn x => func(x) inset set') andalso *) (* forall(set', fn x => exists(set, fn y => func(y) = x)) *) fun project(set : ''a Set, func : ''a -> ''b) : ''b Set = toSet(map func set); (* return a set of sets where each inner set contains item. *) (* Precondition: setofSet : 'a Set Set andalso item : 'a andalso *) (* forall(setofSet, fn set => item notinset set) *) fun addItem(setofSet : ''a Set Set, item : ''a) : ''a Set Set = if isEmpty(setofSet) then empty else let val aSet = fetch(setofSet); val restSet = remove(setofSet, aSet); val newSet = add(aSet, item); val newSetofSet = addItem(restSet, item) in add(newSetofSet, newSet) end; (* return the powerset of a set *) (* Precondition: set : ''a Set andalso *) (* powerset' = powerset(set) andalso *) (* POWERSET : ''a Set Set is the powerset of set *) fun powerset(set : ''a Set) : ''a Set Set = if isEmpty(set) then add(empty, empty) else let val item = fetch(set); val restSet = remove(set, item); val restPower = powerset(restSet) in union(restPower, addItem(restPower, item)) end; (* create a set of integers in a range *) fun range(first : int, last : int) : int Set = if first > last then empty else add(range(first + 1, last), first); (* return the largest integer in a range that satisifies a predicate *) fun max(first : int, last : int, pred : int -> bool) : int = if last < first then raise SetException("max: predicate is never true") else if pred(last) then last else max(first, last-1, pred); end (* SET *)