Removing element from a list - prolog

I know this question has been asked already, but I just want to ask about my specific implementation. I'm writing this function just to practice Prolog and better understand Prolog. Here's what I have:
del(Ele, [H], [H]) :- Ele \= H.
del(Ele, [H|T], [H|New]) :-
Ele \= H,
del(Ele, T, [New]).
The idea is that I will add an element to a new list called New if the element I want to delete is not equal to H. From what I understand, my code isn't working because my code stops when I reach an element where Ele \= H. Any ideas how to fix this?
For example, del(5, [3,4,5,6,7], X) will return false.
Also, are there any better solutions? It seems like a bad solution to keep adding every element in a list to a new list, since this would be slow for a large list. I'd rather just keep the elements currently in the list, find element(s) that match Ele, remove that element, and then return the list.

You have described some cases where del/3 should hold. But these are only cases where Ele is not equal/unifiable to the elements in the list. There are several things missing:
What about the empty list?
What, if Ele is equal to the element?
So you need to add further clauses. (Later you might also remove some, for reasons of redundancy).
If you are using SWI, B, SICStus, or YAP, consider to use dif/2 in place of (\=)/2. prolog-dif
Here is the reason why dif/2 is so helpful in this case. With dif/2 you would have a pure monotonic program. And you could try it out directly:
?- del(5, [3,4,5,6,7], X).
false.
The same problem you had. Let me just restate what the problem is: You expect that something should hold, but it does not. So the relation is too narrowly defined. If I generalize the query, I might get a better answer. Try del(E, [3,4,5,6,7], X). but again the same false. So I'll try an even more general query:
?- del(E, Xs, Ys).
Xs = Ys, Ys = [_A], dif(E,_A)
; ... .
Looks perfect to me! Maybe another answer:
?- del(E, Xs, Ys).
Xs = Ys, Ys = [_A], dif(E,_A)
; Xs = [_A,_B], Ys = [_A|_B], dif(E,_B), dif(E,_A)
; ... .
Now we got an incorrect answer. I will instantiate it a bit to make it better readable:
?- del(e, [a,b], Ys).
Ys = [a|b]
; false.
This answer is clearly incorrect because [a|b] is not a list. And, it's probably the smallest incorrect answer...
What I want to show you by this is that you can most often locate problems without going through it step-by-step. Step-by-step debugging does not even work in imperative languages once you get a more complex control flow (like concurrency) ; and it does not scale at all in Prolog.

Let's trace:
?- trace, del(5, [3,4,5,6,7], X).
Call: (7) del(5, [3, 4, 5, 6, 7], _G218) ? creep
Call: (8) 5\=3 ? creep
Exit: (8) 5\=3 ? creep
Call: (8) del(5, [4, 5, 6, 7], [_G344]) ? creep
Call: (9) 5\=4 ? creep
Exit: (9) 5\=4 ? creep
Call: (9) del(5, [5, 6, 7], [[]]) ? creep
Fail: (9) del(5, [5, 6, 7], [[]]) ? creep
Fail: (8) del(5, [4, 5, 6, 7], [_G344]) ? creep
Fail: (7) del(5, [3, 4, 5, 6, 7], _G218) ? creep
false.
So you can see your code is actually failing when it gets to the 5 because 5 \= 5 is false. Your first rule is never matched because the list has more than one item in it. The second rule recurs "correctly" after finding 5 \= 3 and 5 \= 4 but since you have no 5 = 5 case in any of your rules, the failure happens there.
Incidentally, let's see what happens when 5 does not occur in the list:
?- trace, del(5, [3,4,6,7], X).
Call: (7) del(5, [3, 4, 6, 7], _G350) ? creep
Call: (8) 5\=3 ? creep
Exit: (8) 5\=3 ? creep
Call: (8) del(5, [4, 6, 7], [_G473]) ? creep
Call: (9) 5\=4 ? creep
Exit: (9) 5\=4 ? creep
Call: (9) del(5, [6, 7], [[]]) ? creep
Fail: (9) del(5, [6, 7], [[]]) ? creep
Fail: (8) del(5, [4, 6, 7], [_G473]) ? creep
Fail: (7) del(5, [3, 4, 6, 7], _G350) ? creep
false.
This is why I said "correctly" before: your inductive case isn't right either. For one thing, you have del(Ele, T, [New]) but up above you have del(Ele, [H|T], [H|New]) so you're unwrapping the list an extra time on the right (this is why our trace has [[]] in it). But #false hit the larger issue which is that you simply never account for the case where you actually find what you are looking to delete. :) You also don't handle the case where the list is empty.
It is an unfortunate fact of life that traversing data structures and looking at each item is going to be O(N). Another unfortunate fact is that in functional and declarative languages (languages that lack "assignables") modifying a list means copying at least part of the list. There are more efficient ways to go about this in Prolog (you could use difference lists, for instance) but they will share the same basic problem. Prolog efficiency is a rather large topic. I'd tell you to not worry about it too much up front, but it has a way of becoming your concern pretty quickly. But in this case, no, there isn't really a substantially more efficient approach using destructive updates.

Related

Prolog - infinite loop

I want to check if element is in the middle of list.
I search middle element and next I check if is a member of list, but I get infinite loop.
My predicates:
remove_first([_,H1|T], [H1|T]).
remove_last([_],[]).
remove_last([H|T], [H|T2]) :- remove_last(T, T2).
remove_first_and_last([X],[X]).
remove_first_and_last(In, Out) :-
remove_first(In, Out1),
remove_last(Out1, Out).
middle([X], [X]).
middle(In, X) :-
remove_first_and_last(In, Out),
middle(Out, X).
member(X, [X|_]).
member(X, [_|T]) :- member(X, T).
is_middle(X, In) :-
middle(In, Out),
member(X, Out), !.
And when I call is_middle(1,[2,1,3]) then I get true.
But when I call is_middle(1,[2,2,3]) then I don't get a result. Interpreter don't interrupt the processing.
In a situation as yours, you have two options. Either wade through walls of text of traces as you can see in another answer, or try to reduce first what you have to understand. I prefer the latter for I don't like to read much.
But your major problem is this. You said:
And when I call is_middle(1,[2,1,3]) then I get true.
Yes, Prolog found a solution, but it did not find it once but infinitely many times. Just hit SPACE or ; to see this:
?- is_middle(1,[2,1,3]).
true
; true
; true
; true
; true
; ... .
So, already your first query was problematic. The best way to observe this, is to add false to this query:
?- is_middle(1,[2,1,3]), false.
loops.
Now, let's try to reduce the size of the query. We can narrow it down to:
?- is_middle(1,[1]), false.
loops.
With this we can now look at your program. Before anything else I'll remove the cut. It is misplaced anyway.
To understand what is actually happening, I will narrow down your program by inserting false into it. With these extra goals it is possible to eliminate a lot of unnecessary detail. And still, the remaining program called a failure-slice is of relevance to us, if it is still looping.
remove_first_and_last([X],[X]).
remove_first_and_last(In, Out) :- false,
remove_first(In, Out1),
remove_last(Out1, Out).
middle([X], [X]) :- false.
middle(In, X) :-
remove_first_and_last(In, Out),
middle(Out, X), false.
is_middle(X, In) :-
middle(In, Out), false,
member(X, Out).
Compare this to your original program! Much less reading. To fix the problem you have to fix something in the remaining fragment. I suggest to remove the fact remove_first_and_last([X],[X]). This fact suggests that something is removed, but for this very case, nothing is removed.
For a solution using a dcg directly:
is_middle(E, Es) :-
phrase(middle(E), Es).
middle(E) --> [E].
middle(E) --> [_], middle(E), [_].
That is as short as it can get, but it has a tiny problem: It does not compute the answer determinately. You can see this by looking at the answer:
?- is_middle(1, [2,1,3]).
true
; false.
This ; false is an indication that Prolog was not able to finish the computation determinately. In other words, some space is left. You might be tempted to use a cut. Resist!
If you are really into speed, take the fastest version:
is_middle(X, Xs) :-
Xs = [_|Cs],
middle_el(Cs, Xs, X).
middle_el([], [X|_], X).
middle_el([_,_|Cs], [_|Xs], X) :-
middle_el(Cs, Xs, X).
In case you want #DanielLyons' interpretation which admits even-length lists to have two middle elements, see how easy it is to adopt above grammar definition. Simply add the following two rules:
middle(E) --> [E,_].
middle(E) --> [_,E].
Alternatively, combine all four rules into one:
middle(E) --> [E] | [E,_] | [_,E] | [_], middle(E), [_].
For the fastest solution, things are a bit more complex ...
is_middle_dl(X, Xs) :-
Xs = [_|Cs],
middle_el_dl(Cs, Xs, X).
middle_el_dl([], [X|_], X).
middle_el_dl([_|Cs], Xs, X) :-
middle_el_dl2(Cs, Xs, X).
middle_el_dl2([], [A,B|_], X) :-
( X = A ; X = B ).
middle_el_dl2([_|Cs], [_|Xs], X) :-
middle_el_dl(Cs, Xs, X).
To check it, I use:
?- length(Xs, N), N mod 2 =:= 0, is_middle_dl(X, Xs).
Xs = [X,_A], N = 2
; Xs = [_A,X], N = 2
; Xs = [_A,X,_B,_C], N = 4
; Xs = [_A,_B,X,_C], N = 4
; Xs = [_A,_B,X,_C,_D,_E], N = 6
; Xs = [_A,_B,_C,X,_D,_E], N = 6
; Xs = [_A,_B,_C,X,_D,_E,_F,_G], N = 8
; Xs = [_A,_B,_C,_D,X,_E,_F,_G], N = 8
; Xs = [_A,_B,_C,_D,X,_E,_F,_G,_H,_I], N = 10
; Xs = [_A,_B,_C,_D,_E,X,_F,_G,_H,_I], N = 10
; ... .
Debugging Prolog takes some different skills, so let's take the long road there.
First, let's notice something interesting about your two sample queries. The first one succeeds, and it should; the second one should fail, but instead it loops. This tidbit is a clue: it suggests that we're trying to handle a false case. This is a common mistake among people using Prolog after other languages. In Prolog, it's often enough to be explicit about successful cases and just let failures happen through failed unifications.
The standard tool for debugging Prolog is trace/0. The idea is, you activate trace mode and then run your query, like this:
?- trace, is_middle(1,[2,2,3]).
The trouble with trace/0 is that it can take some effort to understand what's happening with it. Each line starts with one of these four verbs: call, exit, redo, or fail. Then there's a number which indicates the nesting level of the call. The call and redo verbs tell you that you're entering a computation; exit and fail tell you a computation is ceasing and the nesting level is about to decrease. Call/exit are the normal case, fail/redo are what makes Prolog special, the non-determinism. In general, an infinite loop will look like some prefix of meaningful work (or possibly not) followed by an endlessly repeating chunk of output from trace. And we see that here. Prefix:
Call: (8) is_middle(1, [2, 2, 3]) ? creep
Call: (9) middle([2, 2, 3], _G1194) ? creep
Call: (10) remove_first_and_last([2, 2, 3], _G1194) ? creep
Call: (11) remove_first([2, 2, 3], _G1194) ? creep
Exit: (11) remove_first([2, 2, 3], [2, 3]) ? creep
Call: (11) remove_last([2, 3], _G1197) ? creep
Call: (12) remove_last([3], _G1190) ? creep
Exit: (12) remove_last([3], []) ? creep
Exit: (11) remove_last([2, 3], [2]) ? creep
Exit: (10) remove_first_and_last([2, 2, 3], [2]) ? creep
Repeating chunk:
Call: (10) middle([2], _G1200) ? creep
Exit: (10) middle([2], [2]) ? creep
Exit: (9) middle([2, 2, 3], [2]) ? creep
Call: (9) member(1, [2]) ? creep
Call: (10) member(1, []) ? creep
Fail: (10) member(1, []) ? creep
Fail: (9) member(1, [2]) ? creep
Redo: (10) middle([2], _G1200) ? creep
Call: (11) remove_first_and_last([2], _G1200) ? creep
Exit: (11) remove_first_and_last([2], [2]) ? creep
Now you can see it would be much easier to trigger the bad behavior just with this query:
[trace] ?- is_middle(2,[3]).
Call: (7) is_middle(2, [3]) ? creep
Call: (8) middle([3], _G398) ? creep
Exit: (8) middle([3], [3]) ? creep
Call: (8) member(2, [3]) ? creep
Call: (9) member(2, []) ? creep
Fail: (9) member(2, []) ? creep
Fail: (8) member(2, [3]) ? creep
Redo: (8) middle([3], _G398) ? creep
Call: (9) remove_first_and_last([3], _G398) ? creep
Exit: (9) remove_first_and_last([3], [3]) ? creep
Call: (9) middle([3], _G401) ? creep
Exit: (9) middle([3], [3]) ? creep
Exit: (8) middle([3], [3]) ? creep
Call: (8) member(2, [3]) ? creep
Call: (9) member(2, []) ? creep
Fail: (9) member(2, []) ? creep
Fail: (8) member(2, [3]) ? creep
Redo: (9) middle([3], _G401) ? creep
Now it should be clear that the problem has to do with the interplay of middle/2, remove_first_and_last/2 and member/2. Your definition of member/2 is exactly the standard definition so it probably isn't to blame. Now, interestingly, you have middle/2 calling both itself and remove_first_and_last/2. And both middle/2 and remove_first_and_last/2 have an identical clause: m([X], [X]).
This kind of thing is a great generator of infinite recursion, because the first thing middle/2 does in its second clause is exactly what it just tried to do and failed with its own first clause. So it can find itself entering a recursive call in the second clause with exactly the same state it had in an earlier failed call to itself.
The solution is to look at remove_first_and_last/2 and realize that your first clause there does not actually remove the first and last element. Removing the remove_first_and_last([X], [X]) clause fixes the code:
[trace] ?- is_middle(2,[3]).
Call: (7) is_middle(2, [3]) ? creep
Call: (8) middle([3], _G398) ? creep
Exit: (8) middle([3], [3]) ? creep
Call: (8) member(2, [3]) ? creep
Call: (9) member(2, []) ? creep
Fail: (9) member(2, []) ? creep
Fail: (8) member(2, [3]) ? creep
Redo: (8) middle([3], _G398) ? creep
Call: (9) remove_first_and_last([3], _G398) ? creep
Call: (10) remove_first([3], _G398) ? creep
Fail: (10) remove_first([3], _G398) ? creep
Fail: (9) remove_first_and_last([3], _G398) ? creep
Fail: (8) middle([3], _G398) ? creep
Fail: (7) is_middle(2, [3]) ? creep
false.
Both your tests also now work:
?- is_middle(1,[2,1,3]).
true.
?- is_middle(1,[2,2,3]).
false.
I think you added the base case here out of a sense of duty to have one. But the reality is that if you have a list of one element, it should fail to unify with remove_first_and_last/2 under any circumstance. This is very similar to handling an error case explicitly with Prolog, which tends to interfere with the working of the machinery.
Now, one thing that's missing is, how do you want to handle even-length lists? What you have right now won't, with or without my change. Even-length lists don't have a middle element; is that what you intend? I suspect it isn't, because of the appearance of member/2 in is_middle/2.
Comments on is_middle/2
What you have here could be restructured like so:
is_middle(X, In) :- middle(In, [X]).
Usage of member/2 isn't buying you anything because middle/2 can't ever produce a non-singleton list in its second argument. But, if it did, because you had even-length lists, it would be profitable. You could even make this code work that way by adding a third clause to middle/2:
middle([X,Y], [X,Y]).
Now see middle/2 works on even-length lists like so:
?- middle([2,1,3,4], X).
X = [1, 3] ;
false.
Now the cut gets you into trouble though. For instance, 1 and 3 are both is_middle/2:
?- is_middle(1, [2,1,3,4]).
true.
?- is_middle(3, [2,1,3,4]).
true.
Unfortunately though, if you ask for middle elements, you just have 1:
?- is_middle(X, [2,1,3,4]).
X = 1.
What happened to 3? You prevented it from being generated with your cut. I am not sure why the cut is here. I think you must have put it in to try and control the infinite recursion, but it doesn't help you, so get rid of it.
Debugging by random addition of cuts is generally not a great idea. A much better approach is using Ulrich Neumerkel's failure slice approach (see this paper or search the tag for more information).
DCG bonus
You can rephrase remove_first_and_last/2 as a DCG rule:
remove_first_and_last --> remove_first, remove_last.
Pretty cool, huh? :) That's because the kind of input/output threading you're doing in that rule exactly what DCG rules get transformed into.
Summary of changes
remove_first_and_last(In, Out) :-
remove_first(In, Out1),
remove_last(Out1, Out).
middle([X], [X]).
middle([X,Y], [X,Y]).
middle(In, X) :-
remove_first_and_last(In, Out),
middle(Out, X).
is_middle(Item,List) :-
append(Left,[Item|Right],List),
length(Left,X),
length(Right,X).
Complex solutions are bad solutions, my friend.
?- is_middle(X,[1,2,3,4,5]).
X = 3 ;
false.
Fully reversible predicate:
?- is_middle(3,L).
L = [3] ;
L = [_G13, 3, _G19] ;
L = [_G13, _G19, 3, _G25, _G28] ;

PROLOG: addOne predicate, what happens when temp. variable hits the base clause, how does Prolog call values?

I need some help with understanding the following Prolog source code:
addone([],[]).
addone([H|T],[H1|T1]):-H1 is H + 1, addone(T,T1).
This code, takes a given list and therefore prints out another one which has +1 added to each argument of it.
I don't understand how exactly this work, if I trace it:
[trace] 69 ?- addone([1,2,3],X).
Call: (6) addone([1, 2, 3], _G1196) ? creep
Call: (7) _G1273 is 1+1 ? creep
Exit: (7) 2 is 1+1 ? creep
Call: (7) addone([2, 3], _G1274) ? creep
Call: (8) _G1279 is 2+1 ? creep
Exit: (8) 3 is 2+1 ? creep
Call: (8) addone([3], _G1280) ? creep
Call: (9) _G1285 is 3+1 ? creep
Exit: (9) 4 is 3+1 ? creep
Call: (9) addone([], _G1286) ? creep
Exit: (9) addone([], []) ? creep
Exit: (8) addone([3], [4]) ? creep
Exit: (7) addone([2, 3], [3, 4]) ? creep
Exit: (6) addone([1, 2, 3], [2, 3, 4]) ? creep
X = [2, 3, 4].
I get to the point:
Call: (9) addone([], _G1286) ? creep
Exit: (9) addone([], []) ? creep
From here I don't understand how when I reach the base clause Prolog recalls its saved values?
Can you please explain me how this thing works, what is the logic behind it?
Thank you in advance, Petar!
I guess the answer you might be looking for is:
When Prolog sees a predicate defined like this (most simple example):
foo([]).
foo([_|_]).
This predicate will now be deterministic on proper lists. In other words, it will succeed exactly once. This is because Prolog can recognize by loooking at the two clauses that they are mutually exclusive. In other words, for any non-empty list the second clause only can apply, and for an empty list the first clause only can apply.
In other words, for a proper list of length Len, after Len calls of the second clause, a call of the first clause will follow. At that point it succeeds, and all recursive calls (which were tail recursive) will succeed, in reverse order of how they were called.
In your example, before the recursive call is even made, a value is calculated and ready to be used when the call succeeds.
One thing here is that when you call with it a second argument a variable, you will keep on unifying this variable with a head of a list (the number you calculated) and a free tail [H1|T1], which you pass to the recursive call addone(T, T1). Only when the first argument is the empty list, will the second argument also be unified with an empty list: addone([], []). Now, on the return from the recursive calls, the list of values (growing from behind) will be unified with the free tails [4|[]], [3|[4|[]]] [2|[3|[4|[]]]], eventually building the final list in the second argument.

Why does my min() function in Prolog not work?

This is my min() function in Prolog that should find the smallest element in a list of numbers. My idea was to test that the Result is smaller or equal to every element in the list. The head of the list is removed until it is empty. When this point is reached, the set in result was correct.
min([], Result).
min([Head|Tail], Result) :-
Result =< Head,
min(Tail, Result).
When consulting this file in SWI-Prolog, it can test if a value is the minimal element with min([5, 3, 7, 6], 3) which returns true. But min([5, 3, 7, 6], X) does not find a value for X but just returns true.
How can I make it find the value for X?
If you turn tracing on you can see what's wrong with your script.
1 ?- trace.
true.
Original version:
/** Version 0 */
min([], Result).
min([Head|Tail], Result) :-
Result =< Head,
min(Tail, Result).
Output:
[trace] 2 ?- min([5,3,7,6],X).
Call: (6) min([5, 3, 7, 6], _G4129) ? creep
Call: (7) _G4129=<5 ? creep
ERROR: =</2: Arguments are not sufficiently instantiated
Exception: (7) _G4129=<5 ? creep
You're trying to compare an unistantiated variable with 5. Solution: swap lines in the script so that the variable is instantiated before the comparison.
/** Version 1 */
min([], Result).
min([Head|Tail], Result) :-
min(Tail, Result),
Result =< Head.
Output:
[trace] 5 ?- min([5,3,7,6],X).
Call: (6) min([5, 3, 7, 6], _G517) ? creep
Call: (7) min([3, 7, 6], _G517) ? creep
Call: (8) min([7, 6], _G517) ? creep
Call: (9) min([6], _G517) ? creep
Call: (10) min([], _G517) ? creep
Exit: (10) min([], _G517) ? creep
Call: (10) _G517=<6 ? creep
ERROR: =</2: Arguments are not sufficiently instantiated
Exception: (10) _G517=<6 ?
[trace] 102 ?- min([5,3,7,6],X).
Call: (6) min([5, 3, 7, 6], _G3067) ? creep
Call: (7) min([3, 7, 6], _G3067) ? creep
Call: (8) min([7, 6], _G3067) ? creep
Call: (9) min([6], _G3067) ? creep
Call: (10) min([], _G3067) ? creep
Exit: (10) min([], _G3067) ? creep
Call: (10) _G3067=<6 ? creep
ERROR: =</2: Arguments are not sufficiently instantiated
Exception: (10) _G3067=<6 ?
This way the script goes a bit further but when computing the minimum of the tail it reaches a comparison with an unistantiated variable again. Solution: change min([], Result). to min([Result], Result).
/** version 2 */
min([Result], Result).
min([Head|Tail], Result) :-
min(Tail, Result),
Result =< Head.
Output:
[trace] 8 ?- min([5,3,7,6],3).
Call: (6) min([5, 3, 7, 6], 3) ? creep
Call: (7) min([3, 7, 6], 3) ? creep
Call: (8) min([7, 6], 3) ? creep
Call: (9) min([6], 3) ? creep
Call: (10) min([], 3) ? creep
Fail: (10) min([], 3) ? creep
Fail: (9) min([6], 3) ? creep
Fail: (8) min([7, 6], 3) ? creep
Fail: (7) min([3, 7, 6], 3) ? creep
Fail: (6) min([5, 3, 7, 6], 3) ? creep
false.
The program now only returns false. This is because you only consider the case the minimum of the tail is smaller than or equal than the head. This program will only return a correct result when the input list is sorted decreasingly (so that the minimum of the tail is smaller than the head, recursively).
[trace] 10 ?- min([5,4,3,2],X).
Call: (6) min([5, 4, 3, 2], _G2469) ? creep
Call: (7) min([4, 3, 2], _G2469) ? creep
Call: (8) min([3, 2], _G2469) ? creep
Call: (9) min([2], _G2469) ? creep
Exit: (9) min([2], 2) ? creep
Call: (9) 2=<3 ? creep
Exit: (9) 2=<3 ? creep
Exit: (8) min([3, 2], 2) ? creep
Call: (8) 2=<4 ? creep
Exit: (8) 2=<4 ? creep
Exit: (7) min([4, 3, 2], 2) ? creep
Call: (7) 2=<5 ? creep
Exit: (7) 2=<5 ? creep
Exit: (6) min([5, 4, 3, 2], 2) ? creep
X = 2 .
So you need to take care of the case when the minimum of the tail is strictly greater than the head by adding the clause:
min([Head|Tail], Result) :-
min(Tail, R1),
Head < R1,
Result is Head.
And here's the final version:
/** version 3 */
min([Result], Result).
min([Head|Tail], Result) :-
min(Tail, Result),
Result =< Head.
min([Head|Tail], Result) :-
min(Tail, R1),
Head < R1,
Result is Head.
(turn tracing off with nodebug.)
The min of an empty list can't be set.
You can just write
min([X], X).
hoping that X is an integer ; I assume it is !
then
min([Head|Tail], Result) :-
% you fetch the min of the rest of the list
min(Tail, R1),
(Head < R1
-> Result = Head
; Result = R1).
My SWI-Prolog reports
?- min([5, 3, 7, 6], X).
ERROR: user://1:18:
=</2: Arguments are not sufficiently instantiated
which makes sense as the first X =< 3 is performed with unbound X. To make the predicate work, you need to follow the definition of minimum, which is not defined for empty lists:
min([X], X).
min([X|L], Min) :-
L = [_|_], % non-empty tail; could be replaced by a cut
min(L, MinL),
Min is min(X, MinL).
(Note that the final line backs off to the built-in min, which is evaluated by is.)
Alternatively, you can take minima of pairs of elements, giving
min([X], X).
min([X,Y|L], Min) :-
MinXY is min(X, Y),
min([MinXY|L], Min).
This version is tail-recursive.
It couldn't possibly have returned true there. X =< 3 causes "ERROR: =</2: Arguments are not sufficiently instantiated". Perhaps you used #=< for comparison, but with it X #=< 3 just succeeds, without instantiating X in any way. So X would get passed unchanged, and min([], X) would just finally succeed - exactly what you've observed.
Your code is wrong in another way too. min([5, 3, 7, 6], 0) succeeds too, and it shouldn't.
others provided you with recursive solutions. For an iterative one, we typically add another, accumulating argument, and pass the Result down the chain unchanged to receive the final value from the accumulator for us:
min([H|T], Result):- min(T,H,Result).
min([], Result, Result).
min([Head|Tail], M, Result) :-
M =< Head -> min(Tail, M, Result)
; min(Tail, Head, Result).
Empty list has no minimum value. An argument list's head is used as initial value for the minimum.

Making a reverse list

I have the following codes. Trying to make a reverse list. but it doesnt work.
reverse([],[H|T]).
reverse([H|T],Z) :- reverse(T,[H|Z]).
I run this in prolog and I get this:
1 ?- trace, reverse([1,2,3],X).
Call: (7) reverse([1, 2, 3], _G396) ? creep
Call: (8) reverse([2, 3], [1|_G396]) ? creep
Call: (9) reverse([3], [2, 1|_G396]) ? creep
Call: (10) reverse([], [3, 2, 1|_G396]) ? creep
Exit: (10) reverse([], [3, 2, 1|_G396]) ? creep
Exit: (9) reverse([3], [2, 1|_G396]) ? creep
Exit: (8) reverse([2, 3], [1|_G396]) ? creep
Exit: (7) reverse([1, 2, 3], _G396) ? creep
true.
this should give me [3,2,1], instead of [1,2,3]. what is going wrong here??
When a list is empty, its reverse is empty.
So
reverse([], []).
In another case, you append the first element of the list at the end of the revese of the rest of the list. so :
reverse([H|T],Z) :-
reverse(T,Z1),
append(Z1, [H], Z).
You almost got it right. What you need is an "accumulator" which collects the result so far and passes it to the return variable at the end of the recursion:
reverse([],Z,Z).
reverse([H|T],Z,Acc) :- reverse(T,Z,[H|Acc]).
Otherwise the reversed list is forgotten as the function returns from the recursive calls. You need to instantiate the accumulator with an empty list when you call reverse/3:
?- reverse([1,2,3],X,[]).
If you do the trace you will see that the second argument does not get instantiated until your original list is empty.

Given [1,2,3] in prolog get back [6,5,3] by reverse accumalation

Q. Given [1,2,3] in Prolog get back [6,5,3] by reverse accumulation
I have the start code:
accumalate([H],[H]).
accumalate([H1 | H2], [Hnew, H2]),
Hnew is H1 + H2.
....
I am looking for basic Prolog solution.
We are not here to do you homework for you. So the best we can do is provide you with some tips. So ask yourself these questions:
What are the base cases here (for which inputs is the output immediate)?
You have accumulate([N], [N])., but what about empty lists?
In what order must the additions be performed?
More specifically, which elements must be added first?
Other than that, I can tell you that you can solve this using three clauses. No other predicates required. Good luck!
Bonus: you may want to define the head of the recursive clause as follows:
accumulate([N|T], [N1,N2|T2]).
Here is my take:
accumulate([],[]).
accumulate([H|T], [H1|T1]):-
sum([H|T],H1),
accumulate(T,T1).
sum([],0).
sum([H|T],Y):-
sum(T,Y1),
Y is H + Y1.
You can of course use a built-in sumlist/2 in place of the hand-crafted sum/2 if you prefer that.
Once you are done with the basic implementation , Try solving this problem in O(n) time. The idea is to start from the first element and keep on adding it to a secondary list till your original list is empty. The secondary list is the reverse list which you need.
If you append the two lists in your recursive step, you will end up having a O(N^2) complexity.
ac([], 0, []).
ac([H|T], ST, [ST|Res]) :-
ac(T, X, Res),
ST is H + X.
accum(List, Res) :-
ac(List, _, Res).
[trace] ?- accum([1,2,3], X).
Call: (6) accum([1, 2, 3], _G376) ? creep
Call: (7) ac([1, 2, 3], _G458, _G376) ? creep
Call: (8) ac([2, 3], _G461, _G454) ? creep
Call: (9) ac([3], _G464, _G457) ? creep
Call: (10) ac([], _G467, _G460) ? creep
Exit: (10) ac([], 0, []) ? creep
Call: (10) _G459 is 3+0 ? creep
Exit: (10) 3 is 3+0 ? creep
Exit: (9) ac([3], 3, [3]) ? creep
Call: (9) _G456 is 2+3 ? creep
Exit: (9) 5 is 2+3 ? creep
Exit: (8) ac([2, 3], 5, [5, 3]) ? creep
Call: (8) _G453 is 1+5 ? creep
Exit: (8) 6 is 1+5 ? creep
Exit: (7) ac([1, 2, 3], 6, [6, 5, 3]) ? creep
Exit: (6) accum([1, 2, 3], [6, 5, 3]) ? creep
X = [6, 5, 3].

Resources