I am trying to implement a custom version of selection sort, by selecting the maximum of the unsorted part and placing it at the end of the output (sorted) list.
I have a problem with the list recursive build. How can I start building the output list from the right?
sel_sort2([], []).
sel_sort2(L, R) :-
max_list(L, M),
delete1(M, L, L1),
append(R, [M], R),
sel_sort2(L1, R).
You don't need to use append (which as pointed in the first comment is fishy). Instead you can write the second clause like:
sel_sort2(L, [E|T]) :-
min(L, E),
del(L, E, L1),
sel_sort2(L1, T).
Where min takes the minimum element from the input list, and this element is on the first position in the result list, L1 is all elements from L without the first occurrence of a given element.
Related
I have this data structure where the elements are always unique:
[[a,b,c], [d,e,f], [y,z]]
Now, I want to write a procedure to get the index of an element, say I have:
indexOf([[a,b,c], [d,e,f], [y,z]], a, H)
and H is 0. Or:
indexOf([[a,b,c], [d,e,f], [y,z]], f, H)
and H is 2.
This is what I have:
indexOf_single([X|_],X,0).
indexOf_single([_|T],X,H) :- indexOf_single(T,X,H1), H is H1 + 1.
indexOf([T],X,H) :- indexOf_single(T,X,H).
indexOf([Head|Tail],X,H) :- indexOf_single(Head,X,H),indexOf(Tail,X,H).
But I'm getting false all the time. Could you please give me any clues to solve it?
Try with
indexOf([Head|_],X,H) :- indexOf_single(Head,X,H).
indexOf([_|Tail],X,H) :- indexOf(Tail,X,H).
I see two errors in your indexOf/3.
(1) in your second clause
indexOf([Head|Tail],X,H) :- indexOf_single(Head,X,H),indexOf(Tail,X,H).
you ask that H is found in the Head (via indexOf_single/3) and in the Tail. And this is impossible when "the elements are always unique".
(2) in your first clause
indexOf([T],X,H) :- indexOf_single(T,X,H).
you search in T only if T is the last sub-list of the first argument.
I'm working on defining a predicate min_in_list/2 that would find the smallest value on a list. If there is less than 2 elements in the list the program should output "Error: There are not enough elements in the list" and if an element on the list is not a digit Eg. [2,a,3]. The program should output "Error: The element is not a number". I created a predicate that would find the smallest value and checking if the list has less than two values but I'm having problem on checking if an element of a list is not a digit and outputting the error message
My code:
min_in_list([Min],_):- write('ERROR: List has fewer than two elements.').
min_in_list([],_):- write('ERROR: List has fewer than two elements.').
min_in_list([Min,_],Min).
min_in_list([H,K|T],M) :-
H =< K,
min_in_list([H|T],M).
min_in_list([H,K|T],M) :-
H > K,
min_in_list([K|T],M).
The test you're looking for is number/1, which tells you whether a value is a number or not. My final code looks like this:
min_in_list([], _) :- domain_error(not_empty_list, []).
min_in_list([X], _) :- domain_error(not_single_item_list, [X]).
min_in_list([X,Y|Rest], Min) :- min_in_list(X, [Y|Rest], Min).
min_in_list(Min, [], Min) :- !.
min_in_list(Min, [X|Rest], FinalMin) :-
( number(X) ->
(NewMin is min(Min, X),
min_in_list(NewMin, Rest, FinalMin))
;
type_error(number, X)
).
I'm still not entirely sure how to format a condition like this, but splitting it into separate predicates seems like an awful waste. Hopefully someone will come along and tell me how to format this so that it is attractive.
If you are using SWI-Prolog, you can simplify things using must_be/2:
min_in_list(Min, [], Min).
min_in_list(Min, [X|Rest], FinalMin) :-
must_be(number, X),
NewMin is min(Min, X),
min_in_list(NewMin, Rest, FinalMin).
The simplest solution can be:
list(Min, [Min]).
list(Min, [H|T]) :- list(PMin, T), Min is min(H, PMin).
However it must be note, that it will be stack overhead on big arrays.
I am trying to define a function in prolog that takes arguments of the form combination(3,[a,b,c,d],L) , the result returns
L=a,b,c
L=a,b,d
L=a,c,d
L=b,c,d
My implementation is as follows:
combination(K,argList,L):-
unknown(X,argList,Y),
Z is select(X,argList),
length(Z,K),
L is Z,
combination(K,Z,L).
unknown(X,[X|L],L).
unknown(X,[_|L],R) :- unknown(X,L,R).
The unknown predicate behaves as follows:
![enter image description here][1]
Please help.
The simplest solution that comes to mind using your definition of unknown/3 is:
combination(0, _, []) :-
!.
combination(N, L, [V|R]) :-
N > 0,
NN is N - 1,
unknown(V, L, Rem),
combination(NN, Rem, R).
unknown(X,[X|L],L).
unknown(X,[_|L],R) :-
unknown(X,L,R).
Explanation: the second clause of combination/3 looks to select an element from the list L, which the predicate unknown/3 does in a linear manner, returning the remainder, Rem. Once the number of elements selected out of list L exceeds N, the base case is triggered (the first clause of combination/3) which terminates the branch. Note that the definition of combination/3 relies on the non-deterministic nature of unknown/3 which leaves choice-points for selecting alternate list elements.
I want to generate all the sublists of a given list with the given property that they have a certain length mentioned as argument and also they have as a containing element a given element which is passed as a parameter. I have managed to do this but with the help of two predicates, and in terms of optimality is very slow:
sublist([], []).
sublist([A|T], [A|L]):-
sublist(T, L).
sublist(T, [_|L]):-
sublist(T, L).
choose(T, L):-
sublist(T, L),
(dimension(2, T); dimension(1, T)),
belongs(f, T).
In here I would like to return through the T parameter of the choose predicate all the sublists of the L list which have the dimension 2 or 1 and which contains the f element. The predicates dimension and member has the same usage as the predefined predicates length, respectively member.Can you please tell me how to incorporate this two conditions within the sublist predicate so that the program builds only those particular sublists?
The following builds subsequences of length MinLen =< Len =< MaxLen. I've no idea why you renamed length and member, so I'm going to use the originals. sublist/4 calls your sublist/2.
sublist(Sub,List,MinLen,MaxLen) :-
between(MinLen,MaxLen,Len),
length(Sub,Len),
sublist(Sub,List).
Note that length is called on two variables, so you get an iterative deepening search. choose/2 can now be defined as
choose(Sub,List) :-
sublist(Sub,List,1,2),
member(f,Sub).
This is the clean solution. If it's is not fast enough, then roll all the conditions into one predicate:
choose(Sub,List),
(Sub = [f] ; Sub = [f,_] ; Sub = [_,f]),
sublist(Sub,List).
I need to do the following: given a list of lists I need to find all possible combinations of the lists such that if some of these lists belong in such a combination, then they have no elements in common and the list created by appending the lists in the combination has a given length. Any ideas?
Example:
Say P= [[1,2,3],[4,5,6],[2,5],[7,9],[7,10],[8],[10]].
N a given number, say N=10. I need to search through P in order to find appropriate lists, with no elements in common, and add them in a list L such that the length of the union of L is 10. So in the above example :
L=[[1,2,3],[4,5,6],[7,9],[8],[10]]. It might be very easy but I'm new in Prolog
Given nobody's answered, and it's been quite a while since I've written anything in Prolog and I figured I needed the practice, here's how you'd do it.
First, to make generating the combinations easier, we create a term to preprocess the lists to pair them with their lengths to avoid having to get the lengths multiple times. The cut avoids needless backtracking:
with_lengths([], []) :- !.
with_lengths([H|T1], [(Len, H)|T2]) :-
length(H, Len),
with_lengths(T1, T2).
Here's the comb/3 predicate, which you use for generating the combinations:
comb(L, R, Max) :-
with_lengths(L, L1),
comb1(L1, R, Max).
comb1/3 does the actual work. The comments explain what's going on:
% Combination works.
comb1([], [], 0).
% Try combining the current element with the remainder.
comb1([(Len, Elem)|T1], [Elem|T2], Max) :-
NewMax is Max - Len,
comb1(T1, T2, NewMax).
% Alternatively, ignore the current element and try
% combinations with the remainder.
comb1([_|T1], T2, Max) :-
comb1(T1, T2, Max).