Defining a list from scratch in prolog - list

So I need to define a list predicate: list(.) that returns true if the list is of the form cons(b,cons(d,cons(e,cons(h,nil)))). for the list bdeh.
I need to define the cons(.,.) binary predicate as well.
So far I have :
cons(atom(A),nil):- cons(A,nil).
cons(A,B):- cons(A, cons(B,_)).
list(atom(A)):-cons(A,nil).
list(A):- list(cons(_,A)).
but I don't think that the list(.) predicate is actually traversing through my cons. Can anyone help out in how to traverse the list or to proceed?

I need to define the cons(.,.) binary predicate as well.
Based on your question, cons/2 is not a predicate, it is a functor. A functor has no inherent semantical meaning. A functor is used to structure data in some way that makes sense to the programmer.
Your predicate list/1 needs to verify that the parameter is a list. Two things are lists:
the nil/0 constant; and
a compound term of the functor cons/2 where the second element is a list as well.
So we can define it like:
list(nil).
list(cons(_,X)) :-
list(X).
How does this work? The first clause simply states that nil is a list: if you call list(nil). it will succeed ("return" true). If you do not give it a nil, it will check the second clause and see if you gave it a compound term of cons/2. If that is not the case the clause (and thus the predicate call) will fail. If it is the case, it will unpack the compound term. Prolog is not interested in the first element (that's why we call it _), the second element we name X, and Prolog will perform a recursive call to list/1 with that second element to check if it is a list as well. Therefore it will traverse through the nested cons/2 structures until it finds a nil (or cut off earlier if the second element is not a nil and not a cons/2 compound term).

Related

Converting list to terms in Prolog

I have to implement the predicate cons(List, Term) that will take a list [Head|Tail] and convert it to terms, represented as next(Head, Tail). How do I do this? I don't even know where to start.
Here is the example of a successful query given in the question:
cons([a,b,c],X). /*query returns X=next(a,next(b,next(c,null))).*/
Doing most anything with lists will require that you consider two cases: the empty list and a list with a head and a sublist. Usually your base case is handling the empty list and your inductive case is handling the list with sublist.
First consider your base case:
cons([], null).
Now deal with your inductive case:
cons([X|Xs], next(X, Rest)) :- cons(Xs, Rest).

Prolog - Modifying and returning list

I want to define predicate which takes a list, adds an element to the list, let's say the number "1", and then returns the list.
I've found out I can add elements to a list using append/3, but I want to use in inside another predicate, thus why I want it to return "my modified list".
My object-oriented mindset tells me to ask the interpreter something like: ?-append(X,5,X). , so that it takes the list X, adds 5 to it, and returns "the new X", but I know that's not how unification works, so my mind is kinda in a glitch.
Can anyone please try to explain how something like this could be achievable?
You are already very close to the solution, so I only rephrase what you are beginning to sense already:
First, you cannot modify a list in pure Prolog.
Instead, you should think in terms of relations between entities. In your case, think in terms of relations between lists.
So, "adding the number 1" to a list is a relation between two lists, which could look like this:
list_with_one(Ls, [1|Ls]).
Note that this works in all directions! You can use it to:
generate answers
test particular cases
"reverse" the direction etc.
So, all you need to do in your case is to think in terms of relations between lists: One without an element, and how this relates to a different list with the element.
Obviously, these two lists will be indicated by different variables and different arguments.
Note in particular that append(X, 5, X) cannot hold: First of all, append/3 is meant to be a relation between lists, and 5 is not a list. Second, assuming you wrote for example append(Xs, [5], Xs), then this would be true if there where a list Xs such that if the element 5 were appended to Xs, the resulting list would again be Xs. Good luck finding such a list... Note also the naming convention to denote lists by letting the variable name end with an s.
It is also falls a bit short to blame this on your "object-oriented mindset", since you can have object oriented programming in Prolog too.
Although lists in Prolog cannot be modified, it is possible to add elements to the end of a list with an unspecified length. In this way, items can be "appended" to a list without creating another list:
:- initialization(main).
append_to_list(List,Item) :-
append_to_list(List,Item,0).
append_to_list(List,Item,Index) :-
% using SWI-Prolog's nth0 predicate
(nth0(Index,List,Check_Item),
var(Check_Item),
nth0(Index,List,Item));
(Next_Index is Index+1,
append_to_list(List,Item,Next_Index)).
main :-
A = [1,2,3|_],
append_to_list(A,4),
append_to_list(A,7),
writeln(A).
In this example, A becomes [1,2,3,4,7|_].

Reverse the last two elements of a list in Prolog

I am trying to write the following predicate in Prolog while not making use of append/3:
lastTwoReversed(List, ListOf2)
which succeeds exactly when ListOf2 contains the last and the second-to-last elements of List in that order (i.e. reversed).
However, I don't know where to start. Any help is appreciated.
You can write a simple recursive predicate with a base case pattern matching on a list consisting of two elements like so:
last_two_reversed([X,Y],[Y,X]).
Since this is probably homework, I think it's best if you try to write the recursive clause yourself.
Simply use the built-in predicate reverse/2:
last_two_reversed([A,B|T],[Y,X]) :-
reverse([A,B|T],[Y,X|_]).
This will fail for lists with strictly less than two elements. A sensible thing to do would be to make it succeed using those two additional rules:
last_two_reversed([],[]).
last_two_reversed([H],[H]).
First of all, the predicate should fail or succeed with empty list or list with only one element??
In mathematical logic the predicate should return true with empty list and one-element list, because there are no last and second to-last elements to reverse.
So if you want to succeed with empty or one element list you should first start with :
lastTwoReversed([],[]).
lastTwoReversed([X],[X]).
(else don't write the above rules).
Next as base you should write:
lastTwoReversed([X,Y],[Y,X]).
and finally for list of length 3 or greater:
lastTwoReversed([X,Y,Z|T],[X|T1]):-lastTwoReversed([Y,Z|T],T1).
Keep in mind that we write [X,Y,Z|T] to specify for list with 3 or more elements so that doesn't match the previous rules.

Using Prolog: Given a list check if the first element of the list equals the last element

Using prolog, I have to create a rule that determines, when given a list, if the first element of the list is equal to the last element of the list. Below is my thinking.
The Base Cases:
1) If The Parameter Is Not A List: Return False
2) If The Parameter Is A List But Empty: Return False
3) If The Parameter Is A List But Has One Element: Return False
The Recursive Step:
Recursively Going Through The List Getting The
First Element And TheLast Element Then Compare
fela() :- false. <-- Base Case One
fela([]):-false. <-- Base Case Two
fela([H]):-false. <-- Base Case Three
fela([H|T]):- H1 is H, H1 == T, fela(T,H1). <-- Recursive Step
Bellow Are Function For First, Last, Member
first(F, [F|_]).
last(L, [H|T]) :- last(L, T).
member(X, [X|_]).
member(X, [_|T]) :- member(X, T).
I am having trouble with my recursive step, I am unsure of how to store the first element, and traverse the list and obtain the last element, then compare the results for a true/false answer. Could someone help me out
Thanks,
Erik :)
Here's an easy one:
fela(L) :- first(E, L), last(E, L).
Stare at that for a minute and let it really sink in.
Actually, it would be right, but your last/2 isn't, simply traversing the list with no base case that will ever succeed. A correct last/2 would look like this:
last(L, [L]).
last(E, [_|L]) :- last(E, L).
I see a lot of confused ideas in your case analysis. For one thing, in Prolog, you don't explicitly return true and false. You simply match what you match and the rest is failure. When dealing with lists, you automatically inherit the base case of the empty list and the inductive case of an element and the remainder of the list. This isn't sufficient to implement fela/1 from scratch because you have no way of remembering what your first element was. So if you want to build it from scratch you'll need a helper predicate so you can keep passing the first element along. It's going to look like this:
fela([H|T]) :- fela(H, T).
fela(First, [First]).
fela(First, [_|Xs]) :- fela(First, Xs).
Notice that we've preserved the analysis of one base case, one inductive case for handling the list. This is the usual situation when processing a recursive data structure. first/2 is a good example of when you don't follow the rule, because you aren't interested in one of the cases. Building the predicate out of first/2 and last/2 lets you escape the case analysis problem altogether, and is (in my opinion) more often what happens in practice.
Now I want to single out some of your ideas here for further comment. First, H1 is H is definitely not what you want. is/2 is exclusively for reducing arithmetic expressions. You will always have a variable on the left and an expression on the right, or it isn't meaningful. You're trying to do some kind of assignment here, but even H1 = H is not helpful here, because while Prolog has variables, it does not have assignables.
H1 is H, H1 == T says, implausibly, that H is both the head of the list and equivalent to the tail. This isn't ever really possible, because the tail is a list and the head is an element. Even if you could craft a situation where that were true, it definitely wouldn't be interesting to this predicate. Your recursive step here is really strange.
Another problem with your case analysis, case #3 should be true. With [X], X is both the first and the last element of the list, so fela/1 should be trivially true for all one-element lists.
I would advocate additional study. I think you have some odd notions that a little more reading might correct.

tell if a given element is in a list of doubles

I've got a list of doubles in the form A = [[1,2],[2,3],[3,4],[5,5]]
What I'm trying to do is create a function that will return true if a number is the first number in any of the doubles. So somefunction(7,A) would return false and somefunction(5,A) would return true.
I've tried this somefunction(A,B) :- A == (B,_) but this doesn't do anything of any use.
member([N,_],As).
But there are two remarks here:
First, do you really want lists like [[1,2],[3,4]]? If you will always have exactly two elements, consider to use pairs. That is, use the functor (-)/2. It is often written Key-Value. You would thus write [1-2,3-4]. Lists of pairs are commonly used, there is keysort/2 which sorts only according to the Key.
Second, a frequent idiom for "name lookup" is the following:
..., P = (Name-Value), member(P, Dict), ...
What is remarkable here is that we do not need a "special" member predicate for lists of pairs or whatever other elements we have. We might search now "by name" or "by value" or both or none ...
Alternatively to doing the recursion yourself, you could use the "higher order" predicate maplist/3 combined with nth0/3 to select only the first elements of the lists and then issue a member/2 call on the result to achieve what you want:
somefunction(Element, List) :-
maplist(nth0(0), List, Firsts),
member(Element, Firsts).
You can do it recursively like this:
Check to see if the value is at the head of the list:
somefunction(A,[[A,_]|_]).
Then recursively check to see if the value is in the rest of the list:
somefunction(A,[BH|BT]) :- somefunction(A,BT).