%%%%%%%%%%%%%% % Sorting: % We'll just provide the 'spec': % L2 is a sorted version of L1 if: % - L1 is a permutation (re-arrangement) of L2, and % - L2 is in ascending order (er, non-decreasing). scrapSort(L1,L2) :- permutation(L1,L2), nondecreasing(L2). % Here're the helper functions: nondecreasing([]). nondecreasing([_]). nondecreasing([F,S|R]) :- F= PIVOT, partition(PIVOT, TAIL, LEFT, RIGHT). /* [+,+,-] */ append([], LIST, LIST). append([HEAD | LIST1], LIST2, [HEAD | LIST3]) :- append(LIST1, LIST2, LIST3). % Here is a another, more verbose version % (the version I started writing myself ... % Note that I'm used to partitioning into three sections, % so that we always *reduce* the size of a partition % (even if our pivot is the maximum value). % Study the above sol'n, to see how the Prolog % makes sure we always recur on smaller lists (even % when the pivot is the maximum value *and* when % it's the minimum value). qsort([],[]). qsort([F|R],L2) :- partition([F|R],F,Sm,Eq,Lr), qsort(Sm,SmSorted), qsort(Lr,LrSorted), append3(SmSorted,Eq,LrSorted,L2). partition([],_,[],[],[]). partition([F|R],Pivot,Smaller,Equal,Larger) :- FPivot, Larger = [F|LargerRest], partition(R,Pivot,Smaller,Equal,LargerRest). append3(L1,L2,L3,All) :- append2(L1,L2,L1and2), append2(L1and2,L3,All). append2([],L2,L2). append2([F|R],L2,[F|AllRest]) :- append2(R,L2,AllRest). /***************** Reflections/thoughts on prolog: * The idea of declarative programming is cool: Just by specifying what *constitutes* a correct answer, you can write a program (and often it's efficient). + Sometimes though, it's too inefficient (scrapSort). + Worse though: to really write Prolog, you need to thoroughly understand *how* it implements searching (badPerm). + Seeing how different 'cultures' compute is mind-expanding; * Pattern matching: Way cool! This is something *any* language can use (ML, Haskell; Scheme has a 'match' library). * The idea of specifying correctness of an answer (separately from an algorithm) makes me a better [Java, whatever] programmer: often having a clean spec of correctness leads directly to clean, correct code. *****************/