I want to Display all list elements that larger than N, my code like
member2(X, [X|_]).
member2(X, [_|T]) :- member2(X,T), X > T, write(X).
Why would you state member2(X, [X|_]) ? Its not the last element yet. You should only stop when there are no more elements to check: member2(X,[]).
And generally:
member2(X,[Y|Ys]) :- (X >= Y -> display(Y), nl; true), member2(X,Ys).
This way you will display all the Ys that are smaller or equal to X.
In your code, T was a list of elements. You cannot compare it to a single elememt X.
You could use include/3 to perform the filtering. For example:
include(<(5),[7,3,2,6,4,5,8],Output).
will unify Output with [7,6,8] (the elements in the second argument that are greater than the number used in the first argument).
Related
puzzling over a problem of trying to return the second to last element in a list written in Prolog. This language is interesting to use but I'm having trouble getting my head wrapped around it. Here is what I have:
secondLast([X], X).
secondLast(X, [Y], X) :- secondLast(Y, K).
secondLast(X, [Y|Z], K) :- secondLast(Y, Z, K).
secondLast([X|Z], Ans) :- secondLast(X, Z, Ans).
so calling secondLast([a, b, c, d], X).
X should equal c.
Any ideas?
Thanks!
you should apply pattern matching:
secondLast([X,_], X).
secondLast([_|T], X) :- secondLast(T, X).
Can be just:
secondLast(L, X) :-
append(_, [X, _], L).
Sergey and CapelliC have offered two nice solutions to the problem. Let's have a look to see what's wrong with the original:
1) secondLast([X], X).
2) secondLast(X, [Y], X) :- secondLast(Y, K).
3) secondLast(X, [Y|Z], K) :- secondLast(Y, Z, K).
4) secondLast([X|Z], Ans) :- secondLast(X, Z, Ans).
In Prolog, since it is about defining relations between entities with predicates, not defining functions, it helps to describe what a predicate means in terms of, "Something is true if some other things are true". The if in Prolog is expressed as :-.
We'll look at clause #4 since this appears to be your main clause. This one says, Ans is the second to last element of [X|Z] if Ans is the second to last element of Z with X as the head. It's unclear what this 3-argument version of secondLast means. However, if the list is 3 or more elements, it seems clear that X will become irrelevant (as will be seen in clauses 2 and 3).
Clause #1 says, X is the second to last element in list [X]. However, the element X is the last and only element in the list [X]. So this clause is logically incorrect.
Clauses #2 is a bit confusing. It introduces a variable in the clause, K, which is only used once and not defined or used anywhere else in the clause. It also ignores X because, as described above, it has become irrelevant since it's no longer a candidate for second-to-last element. Prolog has given you a warning about singleton elements K and X, which is similar to the warning in C that a variable is "defined but never used" or "is assigned a value that is never used". Clause #3 has the same issue.
In all that, I think I can see what you were trying to do, which is to say that, Ans is second to last element of [X|Z] if there's one more element after X, which would be true, but would be limited to being correct if the list [X|Z] is a 2-element list. In other words, your main clause almost assumes that the answer is ultimately X. If it isn't, it attempts to introduce a new candidate, Y in clauses 2 and 3, but this candidate has no way to "make it back" to the original, main clause.
I'll go back now to CapelliC's solution and describe how one comes to it:
1) secondLast([X,_], X).
2) secondLast([_|T], X) :- secondLast(T, X).
The first clause says, X is the second to last element in the 2-element list, [X,_] which is true. And we don't care what the last element is so we just call it, _. We could have called it Y ([X,Y]), but then Prolog would warn about a singleton variable since we don't need or use Y.
The second clause says, X is the second to last element of list [_|T] if X is the second to last element of the tail, T. This is also true of any list that is 3 or more elements. That's fine since the base case, clause one, takes care of the 2-element list. Clause two will, recursively, reduce down to clause one and finally succeed with the right answer. In this second clause, if X is taken from T, then we don't care what the head of the list is since it has become irrelevant, so we use _ as the head in this case (this corresponds to the X in your original clause #4).
In Sergey's answer:
secondLast(L, X) :-
append(_, [X, _], L).
This says, X is second to last element in list L if L is a two element list with X as the first element ([X,_]) appended to the end of some other list (_). Note again that we're using _ for the variables which will have values but we don't care what those values are in this case. So, for example: 2 is the second to last element of [1,2,3] if [1,2,3] is [2,_] appended to some other list and it is: if you append [2,3] to [1] you get [1,2,3].
I'm trying to best understand everything about this code. This is how I currently perceive what's happening:
So I can see if X > Y we swap the elements, if not we recurse down the sublist until we find an X that X > Y, if we do not, then the list is sorted.
Problems I'm having is I don't really understand the base case, bubblesort(Sorted, Sorted). I thought you would need a base case for an empty list? I would really appreciate if someone could describe a sort of step by step description of this program.
bubblesort(List,Sorted) :-
swap(List,List1),
!,
bubblesort(List1,Sorted).
bubblesort(Sorted,Sorted).
swap([X,Y|Rest],[Y,X|Rest]) :- % swaps X with Y if gt(X,Y) is true.
gt(X,Y).
swap([Z|Rest],[Z|Rest1]) :- % calls swap on sublists excluding the heads.
swap(Rest,Rest1).
gt(X,Y) :- % true if X is greater than Y.
X > Y.
We want to build a predicate that gets a list L and a number N and is true if N is the length of the longest sequence of list L.
For example:
?- ls([1,2,2,4,4,4,2,3,2],3).
true.
?- ls([1,2,3,2,3,2,1,7,8],3).
false.
For this I built -
head([X|S],X). % head of the list
ls([H|T],N) :- head(T,X),H=X, NN is N-1 , ls(T,NN) . % if the head equal to his following
ls(_,0) :- !. % get seq in length N
ls([H|T],N) :- head(T,X) , not(H=X) ,ls(T,N). % if the head doesn't equal to his following
The concept is simply - check if the head equal to his following , if so , continue with the tail and decrement the N .
I checked my code and it works well (ignore cases which N = 1) -
ls([1,2,2,4,4,4,2,3,2],3).
true ;
false .
But the true answer isn't finite and there is more answer after that , how could I make it to return finite answer ?
Prolog-wise, you have a few problems. One is that your predicate only works when both arguments are instantiated, which is disappointing to Prolog. Another is your style—head/2 doesn't really add anything over [H|T]. I also think this algorithm is fundamentally flawed. I don't think you can be sure that no sequence of longer length exists in the tail of the list without retaining an unchanged copy of the guessed length. In other words, the second thing #Zakum points out, I don't think there will be a simple solution for it.
This is how I would have approached the problem. First a helper predicate for getting the maximum of two values:
max(X, Y, X) :- X >= Y.
max(X, Y, Y) :- Y > X.
Now most of the work sequence_length/2 does is delegated to a loop, except for the base case of the empty list:
sequence_length([], 0).
sequence_length([X|Xs], Length) :-
once(sequence_length_loop(X, Xs, 1, Length)).
The call to once/1 ensures we only get one answer. This will prevent the predicate from usefully generating lists with sequences while also making the predicate deterministic, which is something you desired. (It has the same effect as a nicely placed cut).
Loop's base case: copy the accumulator to the output parameter:
sequence_length_loop(_, [], Length, Length).
Inductive case #1: we have another copy of the same value. Increment the accumulator and recur.
sequence_length_loop(X, [X|Xs], Acc, Length) :-
succ(Acc, Acc1),
sequence_length_loop(X, Xs, Acc1, Length).
Inductive case #2: we have a different value. Calculate the sequence length of the remainder of the list; if it is larger than our accumulator, use that; otherwise, use the accumulator.
sequence_length_loop(X, [Y|Xs], Acc, Length) :-
X \= Y,
sequence_length([Y|Xs], LengthRemaining),
max(Acc, LengthRemaining, Length).
This is how I would approach this problem. I don't know if it will be useful for you or not, but I hope you can glean something from it.
How about adding a break to the last rule?
head([X|S],X). % head of the list
ls([H|T],N) :- head(T,X),H=X, NN is N-1 , ls(T,NN) . % if the head equal to his following
ls(_,0) :- !. % get seq in length N
ls([H|T],N) :- head(T,X) , not(H=X) ,ls(T,N),!. % if the head doesn't equal to his following
Works for me, though I'm no Prolog expert.
//EDIT: btw. try
14 ?- ls([1,2,2,4,4,4,2,3,2],2).
true ;
false.
Looks false to me, there is no check whether N is the longest sequence. Or did I get the requirements wrong?
Your code is checking if there is in list at least a sequence of elements of specified length. You need more arguments to keep the state of the search while visiting the list:
ls([E|Es], L) :- ls(E, 1, Es, L).
ls(X, N, [Y|Ys], L) :-
( X = Y
-> M is N+1,
ls(X, M, Ys, L)
; ls(Y, 1, Ys, M),
( M > N -> L = M ; L = N )
).
ls(_, N, [], N).
I have this simple program that checks if an X element belongs to a list:
member2(X, [X|_]).
member2(X,[_|T]):- member2(X,T).
I'm trying to write it in an extended form (because in the previous way the behavior is not so clear). So I have write it in the following way:
member2(X, [X|_]).
member2(X,Y):- Y = [_|T],
member2(X,T).
So the meaning is more clear:
I have one fact that represent the base case (the X element belongs to the list if it is in the head of the list).
The rule say that I have to prove two things:
1) Y = [_|T]. This is true because the anonymous variable _ unifies with anything.
2) It recursively search the element X in the tail list.
Ok, I think my reasoning is correct but this second version of the program don't work! I think that maybe the problem could be in the Y = [_|T] section
your program is fine, in both forms. Here yet another way to (re)write it
member2(X, [Y|Ys]) :-
X = Y ; member2(X, Ys).
I guess the textbook example of checking for a member is:
member_check(X, [X|Tail]). % or [X|_] to avoid the warning
member_check(X, [Y|Tail]) :- X \= Y, member_check(X, Tail).
which would probably be clearer than your second attempt?
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.