%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% %CopyrightEnd%
%%
%%
%% Purpose : Functions for manipulating sets as ordered lists.
%% As yet some of these are not very efficiently written.
-module(ordsets1).
-export([new_set/0,is_set/1,set_to_list/1,list_to_set/1]).
-export([is_element/2,add_element/2,del_element/2]).
-export([union/2,union/1,intersection/2,intersection/1]).
-export([subtract/2,subset/2]).
%% new_set()
%% Return a new empty ordered set.
new_set() ->
[].
%% is_set(Set)
%% Return 'true' if Set is an ordered set of elements, else 'false'.
is_set([E|Es]) ->
is_set(Es, E);
is_set([]) ->
true.
is_set([E2|Es], E1) when E1 < E2 ->
is_set(Es, E2);
is_set([E2|Es], E1) ->
false;
is_set([], E1) ->
true.
%% set_to_list(OrdSet)
%% Return the elements in OrdSet as a list.
set_to_list(S) ->
S.
%% list_to_set(List)
%% Build an ordered set from the elements in List.
list_to_set([E|Es]) ->
add_element(E, list_to_set(Es));
list_to_set([]) ->
[].
%% is_element(Element, OrdSet)
%% Return 'true' if Element is an element of OrdSet, else 'false'.
is_element(E, [H|Es]) when E < H ->
false;
is_element(E, [H|Es]) when E == H ->
true;
is_element(E, [H|Es]) when E > H ->
is_element(E, Es);
is_element(E, []) ->
false.
%% add_element(Element, OrdSet)
%% Return OrdSet with Element inserted in it.
add_element(E, [H|_]=Es) when E < H ->
[E|Es];
add_element(E, [H|_]=Es) when E == H ->
Es;
add_element(E, [H|Es]) when E > H ->
[H|add_element(E, Es)];
add_element(E, []) ->
[E].
%% del_element(Element, OrdSet)
%% Return OrdSet but with Element removed.
del_element(E, [H|_]=Es) when E < H ->
Es;
del_element(E, [H|Es]) when E == H ->
Es;
del_element(E, [H|Es]) when E > H ->
[H|del_element(E, Es)];
del_element(E, []) ->
[].
%% union(Set1, Set2)
%% Return the union of Set1 and Set2.
union([H1|Es1], [H2|_]=Es2) when H1 < H2 ->
[H1|union(Es1, Es2)];
union([H1|Es1], [H2|Es2]) when H1 == H2 ->
[H1|union(Es1, Es2)];
union([H1|_]=Es1, [H2|Es2]) when H1 > H2 ->
[H2|union(Es1, Es2)];
union([], Es2) ->
Es2;
union(Es1, []) ->
Es1.
%% union(OrdSets)
%% Return the union of the list of sets.
union([S1,S2|Ss]) ->
union1(union(S1,S2), Ss);
union([S]) ->
S;
union([]) ->
[].
union1(S1, [S2|Ss]) ->
union1(union(S1, S2), Ss);
union1(S1, []) ->
S1.
%% intersection(Set1, Set2)
%% Return the intersection of Set1 and Set2.
intersection([H1|Es1], [H2|_]=Es2) when H1 < H2 ->
intersection(Es1, Es2);
intersection([H1|Es1], [H2|Es2]) when H1 == H2 ->
[H1|intersection(Es1, Es2)];
intersection([H1|_]=Es1, [H2|Es2]) when H1 > H2 ->
intersection(Es1, Es2);
intersection([], Es2) ->
[];
intersection(Es1, []) ->
[].
%% intersection(OrdSets)
%% Return the intersection of the list of sets.
intersection([S1,S2|Ss]) ->
intersection1(intersection(S1,S2), Ss);
intersection([S]) ->
S;
intersection([]) ->
[].
intersection1(S1, [S2|Ss]) ->
intersection1(intersection(S1, S2), Ss);
intersection1(S1, []) ->
S1.
%% subtract(Set1, Set2)
%% Return all and only the elements of Set1 which are not also in Set2.
subtract([H1|Es1], [H2|_]=Es2) when H1 < H2 ->
[H1|subtract(Es1, Es2)];
subtract([H1|Es1], [H2|Es2]) when H1 == H2 ->
subtract(Es1, Es2);
subtract([H1|_]=Es1, [H2|Es2]) when H1 > H2 ->
subtract(Es1, Es2);
subtract([], Es2) ->
[];
subtract(Es1, []) ->
Es1.
%% subset(Set1, Set2)
%% Return 'true' when every element of Set1 is also a member of Set2,
%% else 'false'.
subset([H1|Es1], [H2|Es2]) when H1 < H2 -> %H1 not in Set2
false;
subset([H1|Es1], [H2|Es2]) when H1 == H2 ->
subset(Es1, Es2);
subset([H1|Es1], [H2|Es2]) when H1 > H2 ->
subset([H1|Es1], Es2);
subset([], Es2) ->
true;
subset(Es1, []) ->
false.