/* **************************************************************** */
/*                                                                  */
/*          CSE 428: Examples of programs on lists                  */
/*                                                                  */
/* **************************************************************** */


/* Definition of a relation "appnd" is true iff the third argument 
   is the result of appending the second argument to the second     */

/* Note: this relation is predefined in Prolog as "append"          */

appnd([],L,L).
appnd([X|L],K,[X|M]) :- appnd(L,K,M).

/* **************************************************************** */

/* Definition of a relation "perm" which is true iff the second 
   argument is a permutation of the first                           */

perm([],[]).
perm(L,[X|K]) :- appnd(L1,[X|L2],L), appnd(L1,L2,L3), perm(L3,K).

/* **************************************************************** */

/* Definition of a predicate "ordered" which is true iff 
   its argument is an ordered list                                  */

ordered([]).
ordered([_]).
ordered([X,Y|L]) :- X < Y, ordered([Y|L]).

/* **************************************************************** */

/* Definition of a predicate "slowsort" which is true iff 
   its second argument is an ordered permutation of the first. 
   In practice, this predicate does the sorting of a list, and it is 
   very easy to write (given previos definitions), but it is very 
   slow, because it first generates the possible permutations, and 
   for each of them it checks whether it is ordered, until it finds 
   the ordered one                                                  */

/* This way of sorting a list uses a technique which is called 
   "generate and test": First generate a candidate answer, then 
   test if it a correct answer. The programs generated with this
   technique usually are not very efficient, but they are easy 
   to write. Hence, we can use this technique whenever we are in
   the need of solving a problem quickly and we don't mind 
   (for the moment) about the efficiency of the program.            */                

slowsort(L,K) :- perm(L,K), ordered(K).


/* **************************************************************** */

/* Definition of a predicate "memb" which is true iff the first
   argument occurs in (is a member of) the second argument         */

memb(X,[X|_]).
memb(X,[_|L]) :- memb(X,L).

/* **************************************************************** */

