/*
 *  exchange.pl:	Prolog source code implementing
 *			exchanger.
 *  Versions:	 	1.0 and 2.0
 *  Implemented by:	Psallidas Fotis
 *  std code:		std06170
 *  A.M. code:		1115200600170
 *  Reason:		Logic Programming course
 *  Semester:		Spring 2009
 *
 */

 /* exchange:
  *	find all the possible lists of the basic list
  *	and take the maximum value.
  */
exchange(L,V):-
	findall(R,reverses(L,R),D),
	maxbval(D,V).

 /* reverses:
  *	create all the possible lists of the basic lists.
  */
reverses([],[]).
reverses([ K ] , [ K ]).
reverses([ H | T1 ] ,[ H | T2 ]):-
	reverses(T1,T2).
reverses([ X1 , X2 | T1 ],[ RX1 , RX2 | T2 ]):-
	reverse_num(X1,RX2),
	reverse_num(X2,RX1),
	reverses(T1,T2).

 /* swap_number:
  *	insert the digits of a number into a list	
  */
swap_number(0,[]).
swap_number(D,[ H | T ]):-
	D > 0,
	V is D // 10,
	H is D mod 10,
	swap_number(V,T).
 
 /* reverse:
  *	reverse a list.
  */
revers(A,R) :- 
	reversel(A,[],R).		/* hide the accumulator */
reversel([ X | Y ] , Z , W) :- 
	reversel(Y , [ X | Z ] , W).
reversel([],X,X).

 /* compute:
  *	convert a list of digits into a number
  */
compute([],0).
compute([ H | T ],SN):-
	compute(T,V),
	SN is V*10+H.

 /* reverse_num:
  *	reversing a number.
  *	Insert number's digits into a list,
  *	reverse the list and
  *	convert the list into a number.
  */
reverse_num(NF,NL):-
	swap_number(NF,L),
	revers(L,Q),
	compute(Q,NL).

 /* val:
  *	take the basic value of a list.
  */ 
bval([]  , 0 ).
bval([ X ] , X ).
bval([ H1 , H2  | T ] , D):-
	bval(T , U),	
	D is U+H1-H2.

 /* maxbval:
  *	the max basic value of list of lists.
  */ 
maxbval([ H ] , V):-
	bval(H,V).
maxbval([ H | T ] , V):-
	bval(H,R),
	maxbval(T,D),	
	max(R,D,V).

 /* max:
  *	the max bettwen two numbers.
  */
max(V,D,V):-
	V > D.
max(V,D,D):-
	D >= V.
