I want to write a predicate convert/2. It should work like this
? - convert([a,[a,a],[a,b],[b,a],[[a,b]],[d],c],X).
X = [a,c,[a],[d],[a,b],[[a,b]]]
yes
? - conv
Ok, but can you replace built-in function 'sort' by some other? this is most important here
So, without knowing exactly what your sorting algorithm is, I have created a somewhat generic example to demonstrate the concept:
convert(X, X) :- \+is_list(X).
convert([],[]).
convert([InHead|InTail], OutList) :-
convert(InHead, OutHead),
convert(InTail, OutTail),
append([OutHead], OutTail, UnsortedList),
sort(UnsortedList, DeduplicatedList),
custom_sort(DeduplicatedList, OutList).
custom_sort(List,Sorted) :-
permutation(List,Sorted),
is_sorted(Sorted).
is_sorted([]).
is_sorted([_]).
is_sorted([X,Y|T]) :-
% perform any number of tests on X and Y here
% default is:
X @=< Y,
is_sorted([Y|T]).
This recursively converts each list in the list, then uses the built-in sort to remove duplicates, then applies a custom sort (built on naive sort).
I initially thought that I had cracked your sorting algorithm (sort by depth of the list (where an atom has depth 0), then by length of the list (where an atom has length 0), then by elements of the list) and came up with the following:
list_length(X, 0) :-
\+is_list(X).
list_length(X, Y) :-
is_list(X), length(X, Y).
list_depth(X, 0) :- \+is_list(X).
list_depth([], 0).
list_depth([Head|Tail], Y) :-
list_depth(Head, YH),
list_depth(Tail, YTP),
YT is YTP - 1,
Y is max(YH, YT) + 1.
is_sorted([X,Y|T]) :-
list_length(X, XL),
list_length(Y, YL),
list_depth(X, XD),
list_depth(Y, YD),
( XD < YD ;
( XD = YD,
( XL < YL ;
( XL = YL,
X @=< Y)
)
)
),
is_sorted([Y|T]).
... but this fails for your third example, where [a,[a]],[a,b,c] has depth 2 followed by depth 1, so I present the code above for your enjoyment more than anything else.
Edit: The comment from Boris was enough for me to realise that sorting by flattened length then depth works for all of your examples, which looks like this:
list_length(X, 0) :-
\+is_list(X).
list_length(X, Y) :-
is_list(X),
flatten(X, Z),
length(Z, Y).
list_depth(X, 0) :- \+is_list(X).
list_depth([], 0).
list_depth([Head|Tail], Y) :-
list_depth(Head, YH),
list_depth(Tail, YTP),
YT is YTP - 1,
Y is max(YH, YT) + 1.
is_sorted([X,Y|T]) :-
list_length(X, XL),
list_length(Y, YL),
list_depth(X, XD),
list_depth(Y, YD),
( XL < YL ;
( XL = YL,
( XD < YD ;
( XD = YD,
X @=< Y)
)
)
),
is_sorted([Y|T]).