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|_].
Related
I have a number of lists containing letters and I have written a predicate that checks whether or not there are duplicates present in one of these given lists:
noDuplicates([]).
noDuplicates([H|T]):-
not(member(H, T)),
noDuplicates(T).
I have 10 lists and I want to know if there are no duplicates in any of them, so I made them into sublists of one big list, something like:
[[A,B,C], [C,A,D], [E,F,G]...]]
(So there can be duplicates in the big list, but not the individual sublists).
I get that I have to do the duplicates test 10 times; once for every sublist, but how do I write this in Prolog? I could probably write it down 10 times, but my guess is I can use recursion to make prolog repeat itself until all sublists have been checked.
So basically: I want this predicate to repeat itself N times, until N is 10. I'm really struggling with it though. Does anyone have any idea on what to do?
Let us generalize the question as follows:
You have a predicate p/1 that expresses what you want for a single list.
Thus, to lift this definition to a list of such lists, you can define a predicates ps/1 as follows:
ps([]).
ps([L|Ls]) :-
p(L),
ps(Ls).
Every time you see this pattern, you can use maplist/2. That is, the above is equivalent to:
ps(Ls) :- maplist(p, Ls).
The goal maplist(p, Ls) is true iff p holds for each element L of Ls.
Note that it will limit your understanding of Prolog if you think in terms of "looping" and "repeating". These are imperative notions and only make sense when the list is already fully instantiated. However, from Prolog, we expect more than that: We expect a full-fledged relation to also generate lists for which the relation holds. And in such cases, there is nothing to "repeat" yet: We start from nothing, and ask Prolog what solutions there are in general.
Thus, think in terms of describing when the relation ps/1 holds for lists of lists:
It holds for the empty list [].
It holds for the list [L|Ls] if our initial predicate (p/1) holds for L, and ps/1 holds for the remaining list Ls.
This declarative reading is applicable in all directions, no matter how many list elements are already instantiated, if any. It works for 10 lists just as well as for zero and 50.
I'm totally new in Prolog and I have problems handling a list that contains other lists.
I have some lists like this:
[([5],23),([1],23),([2],43),([4],29),([3],14),([5,1,4,3],47)]
and I am trying to take the (sub)list with the biggest length and put it first at the list
in this example I want the result to be like this:
([5,1,4,3],47),([5],23),([1],23),([2],43),([4],29),([3],14)]
(don't care whether it will be removed or not from it's starting place).
Thanks to all who will try to help
Presuming that you want to use the built-in sort routine (I'm using SWI-Prolog as example here), then the following would work:
calcLen((List,K),(N,List,K)):- length(List,N).
delLen((_,List,K),(List,K)).
sortlen(List,Sorted):-
maplist(calcLen,List,List1),
sort(0,#>=,List1, List2),
maplist(delLen,List2,Sorted).
The two predicates calcLen and delLen insert and remove a length calculation at the front of the pairs in the list -- making them triples. The maplist predicate applies calcLen (and later delLen) to a list.
I'm attempting to write a predicate to remove elements from an ordered list in Prolog. This is part of a homework assignment and I'm very confused about how Prolog's semantics work in general.
When I try the following function with the goal rdup([1,2], L). I get false. I've traced the goal and it looks like I'm not supposed to be building up the result list the way I am building it up with recursive calls to rdup. I'm not certain how I should be building up the result list. Here's the function:
rdup([],M).
rdup([X],[X]).
rdup([H1,H2|T], M) :- H1 \= H2, rdup(T, [M,H1,H2]).
rdup([H1,_|T], M) :- rdup(T, [M,H1]).
Can anyone tell me where my reasoning is wrong or how one is supposed to build up a list recursively in Prolog?
Firstly, it's not functions.
It's predicates, they only say, what's true, what's not, and under what conditions.
Here are your program:
rdup([],[]).
rdup([X],[X]).
rdup([H,H|T], M) :- rdup([H|T], M).
rdup([H1,H2|T], [H1|M]) :- H1 \= H2, rdup([H2|T], M).
Now a little bit of explanation.
Firstly, what says "rdup(X,Y)"? It's not saying "Take ordered list in X, and put list X without duplicates in Y", but it says "This fact will be true, if Y is an list X without duplicates, in assumption that X is an ordered list". Notice, that we don't talk about "returning values" or sth like that.
First line says, that the empty list is a list without duplicates of empty list. Quite obvious, right?
Next line is basically the same, but with one element.
Third line says, that if we have list, which consists from two same elements H and tail T, then the ordered list of this list ([H,H|T]) is the same, as it would be with only one element H. That's why we have "M" in both predicates unmodified.
I hope you will analyse the last predicate on your own, Prolog is not as hard as it looks to be. Good luck!
let's say we have a list of elements:
[(a,b); (c,d); (e,f)]
What function would check if element (lets say A, where A=(x,y)) is in the list or not?
Use List.mem to do the search for a match.
let a = (3,4)
List.mem a [(1,2); (3,4); (5,6)]
You can also use List.memq if you want to check if the two items both reference the same entity in memory.
Here's a hint on how to write this yourself. The natural way to to process a list is to initially look at the first element, then check the remainder of the list recursively until you have an empty list. For this problem, you could state the algorithm in English as follows:
If the list is empty then the item is not in the list,
else if the first list element equals the item then it is in,
else it is the answer to (Is the item in the remainder of the list?)
Now you just need to translate this into OCaml code (using a recursive function).
In general, if you can describe what you want to do in terms of smaller or simpler parts of the problem, then writing the recursive code is straightforward (although you have to be careful the base cases are correct). When using a list or tree-structured data the way to decompose the problem is usually obvious.
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).