/*********************************************************************/
/*								     */
/* util_list 							     */
/*								     */
/* Copyright (C) 1997 Thanaruk Theeramunkong (ping@jaist.ac.jp)      */ 
/*                    Manabu Okumura         (oku@jaist.ac.jp)       */
/*                    Susumu Kunifuji        (kuni@jaist.ac.jp)      */
/*                    Hiroki Imai            (imai@cs.titech.ac.jp)  */
/*								     */
/*					     	9 May 1997	     */
/*								     */
/*								     */
/*********************************************************************/

/****************************************/
/*        List-Relative utility         */
/*                                      */
/*                        T.THANRUK     */
/*                                      */
/*               1990/12/10 ( MON )     */
/*                                      */
/****************************************/

% and_n_d/3  % and no double.
% append/3
% append_dl/3
% cnt_lst/2 
% delete/3
% exorlist/3
% flatten/2
% flatten_dn/2
% insert/3
% length1/3
% no_double/2
% member/2
% ordered/1
% partition/4
% permutation/2
% prefix/2
% quicksort/3
% dquicksort/3
% range/3
% reverse/2
% reverse1/2
% suffix/2
% write_list/1
% list/1
% inc/2
% ex_lst/3
% ex_or/3
% count_lst/2

% append(Xs,Ys,XsYs)

append([],Ys,Ys).
append([X|Xs],Ys,[X|Zs]) :-
	append(Xs,Ys,Zs).

% append_dl(X-Y,Y-Z,X-Z)
append_dl(X-Y,Y-Z,X-Z).


% delete(List,X,HasNoXs)

delete([X|Xs],X,Ys) :-
	!,delete(Xs,X,Ys).
delete([X|Xs],S,[X|Ys]) :-
	!,delete(Xs,S,Ys).
delete([],_S,[]).

% exorlist/3

exorlist([],_Y,[]) :- !.
exorlist([X|Xs],Y,Z) :-	
	member(X,Y),!,
	exorlist(Xs,Y,Z).
exorlist([X|Xs],Y,[X|Z]) :-
	exorlist(Xs,Y,Z).

% orlist/3

orlist([],Y,Y) :- !.
orlist([X|Xs],Y,Z) :-	
	member(X,Y),!,
	orlist(Xs,Y,Z).
orlist([X|Xs],Y,[X|Z]) :-
	orlist(Xs,Y,Z).

% flatten(Xs,Ys)

flatten([X|Xs],Ys) :-
	flatten(X,Ys1),
	flatten(Xs,Ys2),
	append(Ys1,Ys2,Ys).
flatten([],[]) :- !.
flatten(X,[X]) :-
	atom(X),!.

% insert(X,List,NList)

insert(X,[],[X]).
insert(X,[Y|Ys],[Y|Zs]) :-
	X > Y,!,
	insert(X,Ys,Zs).
insert(X,[Y|Ys],[X,Y|Ys]) :-
	X =< Y,!.
% length1(List,No_Mem)

length1([],0) :- !.
length1([_X|Xs],N) :- 
	length1(Xs,N1),
	N is N1+1.

% nd_reverse(Xs,Ys)

nd_reverse(Xs,Ys)  :-
	nd_reverse(Xs,[],Ys).

nd_reverse([X|Xs],Revs,Ys) :-
	member(X,Revs),!,
	nd_reverse(Xs,Revs,Ys).
nd_reverse([X|Xs],Revs,Ys) :-
	nd_reverse(Xs,[X|Revs],Ys).
nd_reverse([],Ys,Ys).

% no_doubles(Xs,Ys)

no_doubles([X|Xs],Ys) :-
	member(X,Xs),!,
	no_doubles(Xs,Ys).
no_doubles([X|Xs],[X|Ys]) :-
	no_doubles(Xs,Ys).
no_doubles([],[]).

% member(Element,List)

member(X,[X|_List]).
member(X,[_Y|List]) :-
	member(X,List).

% ordered(List)

ordered([_X]).
ordered([X,Y|Ys]) :-
	X =< Y,ordered([Y|Ys]).

% partition(List,X,BList,SList)

partition([X|Xs],Y,[X|Ls],Bs) :-
	X @=< Y,
	partition(Xs,Y,Ls,Bs).
partition([X|Xs],Y,Ls,[X|Bs]) :-
	X @>= Y,
	partition(Xs,Y,Ls,Bs).
partition([],_Y,[],[]).

% permutation(List,ShuffleList)

permutation(Xs,[Z|Zs]) :-
	select(Xs,Z,Ys),
	permutation(Ys,Zs).
permutation([],[]).

% prefix(Prefix,List)

prefix([],_Ys).
prefix([X|Xs],[X|Ys]) :-
	prefix(Xs,Ys).

% quicksort(Xs,Ys)

quicksort([],[]) :- !.
quicksort([X|Xs],Ys) :-
	partition(Xs,X,Littles,Bigs),
	quicksort(Littles,Ls),
	quicksort(Bigs,Bs),
	append(Ls,[X|Bs],Ys).

% dquicksort(Xs,Ys) with differential list

dqsort(List,Result) :- 
	dqsort1(List,Result-[]).

dqsort1([],X-X) :- !.
dqsort1([X|Xs],X1-X3) :-
	partition(Xs,X,Littles,Bigs),
	dqsort1(Bigs,X2-X3),
	dqsort1(Littles,X1-[X|X2]).

% range(M,N,Ns)

range(N,N,[N]).
range(M,N,[M|Ns]) :-
	M < N,
	M1 is M1+1,
	range(M1,N,Ns).

% reverse(List,RevList) = called "Naive reverse"

reverse([],[]).
reverse([X|Xs],Zs) :-
	reverse(Xs,Ys),
	append(Ys,[X],Zs).

% reverse1(List,RevList) = called "Reverse-accumulate"

reverse1(Xs,Zs) :-
	reverse1(Xs,[],Zs).

reverse1([],Zs,Zs).
reverse1([X|Xs],Ys,Zs) :-
	reverse1(Xs,[X|Ys],Zs).

% select(HasXs,X,OnelessXs) :-

select([X|Xs],X,Xs).
select([X|Xs],S,[X|Ys]) :-
	select(Xs,S,Ys).

% suffix(Suffix,List)

suffix(Xs,Xs).
suffix(Xs,[_Y|Ys]) :-
	suffix(Xs,Ys).


flatten_dn(List,OList) :-
	flatten_dn1(List,OList-[]).

flatten_dn1([],X-X) :- !.
flatten_dn1([L|List],X1-X2) :-
	flatten_dn1(L,X3-X2),
	flatten_dn1(List,X1-X3).
flatten_dn1(A,P-X) :- 
	atom(A),!,
	(member(A,X) ->
	   P = X ;
	   P = [A|X]).

flatten_d(List,OList) :-
	flatten_d1(List,OList-[]).

flatten_d1([],X-X) :- !.
flatten_d1([L|List],X1-X2) :-
	flatten_d1(L,X3-X2),
	flatten_d1(List,X1-X3).
flatten_d1(A,[A|X]-X) :- 
	atom(A),!.

moveout(_A,[],[],0) :- !.
moveout(A,[A|List],List,1) :- !.
moveout(A,[L|List],[L|OList],N) :- 
	moveout(A,List,OList,N).
	
setop([],List2,[],List2,[],List2) :- !.	
setop([L|List1],List2,OAndSet,[L|Orset],OExSet1,ExSet2) :-
	moveout(L,List2,OList,N),
	(
	  N =:= 1 ->
	     OAndSet = [L|AndSet],
	     OExSet1 = ExSet1
	 ;
	     OAndSet = AndSet,
	     OExSet1 = [L|ExSet1]
	),
	setop(List1,OList,AndSet,Orset,ExSet1,ExSet2).

and_n_d([],_List,[]) :- !.
and_n_d([L|List1],List2,[L|OList]) :-
	member(L,List2),!,
	and_n_d(List1,List2,OList).
and_n_d([_L|List1],List2,OList) :-
	and_n_d(List1,List2,OList).

or_n_d([],List2,List2) :- !.
or_n_d([L|List1],List2,[L|OList]) :-
	\+ member(L,List2),!,
	or_n_d(List1,List2,OList).
or_n_d([_L|List1],List2,OList) :-
	or_n_d(List1,List2,OList).

filter_l([],_List2,[]) :- !.
filter_l([L|List1],List2,[L|OList]) :-
	\+ member(L,List2),!,
	filter_l(List1,List2,OList).
filter_l([_L|List1],List2,OList) :-
	filter_l(List1,List2,OList).


cnt_lst(X,N) :-
	cnt_lst(X,0,N).

cnt_lst([],NN,NN) :- !.
cnt_lst([_X|L],N1,NN) :-
	N2 is N1+1,
	cnt_lst(L,N2,NN).

write_list([L|List]) :-  write(L), write('\n'),write_list(List).
write_list([]).

write_list(_N,[]) :- !.
write_list(N,[L|List]) :- 
	write(N),write(' : '),
	write(L),write('\n'),
	N1 is N+1,
	write_list(N1,List).

list([]) :- !.
list([_|_]).

inc(INum,ONum) :-
	ONum is INum+1.

ex_lst([],_List2,Result) :- Result = [].
ex_lst([L|List1],List2,Result) :-
	member(L,List2),!,
	ex_lst(List1,List2,Result).
ex_lst([L|List1],List2,[L|Result]) :-
	\+ member(L,List2),!,
	ex_lst(List1,List2,Result).

ex_or([],_NonTerm,[]) :- !.
ex_or([T|TmpFTermL],NonTerm,OutTermL) :-
	member(T,NonTerm),!,
	ex_or(TmpFTermL,NonTerm,OutTermL).
ex_or([T|TmpFTermL],NonTerm,[T|OutTermL]) :-
	ex_or(TmpFTermL,NonTerm,OutTermL).

count_lst(L,N) :-
	count_lst(L,0,N).

count_lst([],ON,ON) :- !.
count_lst([_L|List],IN,ON) :-
	IN1 is IN+1,
	count_lst(List,IN1,ON).
