I want, given 2 lists, to merge them into a third one but each element of the third list is a list of the first and second list's elements.
E.g. given the list1 [1,2,3] and list2 [1,2,3] I want the final list to be [[1,1],[2,2],[3,3]]
What I've done so far is
merge([],[],Z).
merge([H1|T1],[T2|T2],Z):-
append([H1],[H2],W),merge(T1,T2,[W,Z]).
but I get a False result. Why isn't it working?
There are some flaws in your code:
when the first two lists are empty, the result must be an empty list too;
Instead of [T2|T2] you should write [H2|T2] to represent the second list;
there is no need to use append([H1],[H2],W) to create a list with two elements, just write [H1,H2];
since the recursive call must merge the tails of the first and second lists, there is no way the result of this call to be a list starting with the element [H1,H2].
Thus, a correct definition for that predicate is as follows:
my_merge([], [], []).
my_merge([H1|T1], [H2|T2], [[H1,H2]|T3]):-
my_merge(T1, T2, T3).
Examples:
?- my_merge([a,b,c], [1,2,3], L3).
L3 = [[a, 1], [b, 2], [c, 3]].
?- my_merge(L1, L2, [[1,a],[2,b],[3,c]]).
L1 = [1, 2, 3],
L2 = [a, b, c].
Remark Consider the possibility of representing the pair [H1,H2] as H1-H2, as the latter representation is more commonly used in Prolog.
Related
the following code works, but if need help to understand how it is working.
%Multiplication of List Elements, Lists have same length
listmulti([],[],[]).
listmulti([H1|B1],[H2|B2],[Result|Spare]) :-
listmulti(B1,B2,Spare),
Result is H1 * H2.
Everything is understandable, but not the Spare variables. Without it the code don't work.
I added my Prolog trace here, to see what happens.
trace,(listmulti([2,1],[3,5],Result)).
Call:listmulti([2, 1], [3, 5], _5956)
Call:listmulti([1], [5], _6268)
Call:listmulti([], [], _6274)
Exit:listmulti([], [], [])
Call:_6272 is 1*5
Exit:5 is 1*5
Exit:listmulti([1], [5], [5])
Call:_6266 is 2*3
Exit:6 is 2*3
Exit:listmulti([2, 1], [3, 5], [6, 5])
Result = [6, 5]
What are the _5956 and so on digits? Help variables from Prolog?
What happens with the Spare variable, it is Empty all the time? Why i need the Spare variable? Why I can't write only [Result] so like this
listmulti([H1|B1],[H2|B2],[Result])
Thanks for your answers in advance and best greetings.
Prolog communicates the results of computations by binding variables to terms. Variables can start out unbound, i.e., not bound to any value, and can become bound during a computation by unification.
To some extent you already know this. After all, when you write a query like
?- listmulti([2,1],[3,5],Result).
you do not specify a value for Result -- it is unbound. But when you run the query, Prolog will bind Result to a term and tell you what it is:
Result = [6, 5].
We can visualize this by printing the value of Result before and after it is bound by calling listmulti:
?- write('before the query, Result is: '), write(Result), nl,
| listmulti([2,1], [3,5], Result),
| write('after the query, Result is: '), write(Result), nl.
before the query, Result is: _G1699
after the query, Result is: [6,5]
Result = [6, 5].
In the beginning, Result is just some unbound variable, which is shown as _G1699 in this case. (Different variables have different numbers so you can distinguish them.) After the query is run, that same variable is now bound to the list [6, 5].
This is also what the tracer was telling you, although it takes some practice to read its output:
Call:listmulti([1], [5], _6268)
...
Exit:listmulti([1], [5], [5])
This is a pair of states just before and just after executing listmulti([1], [5], Spare). The current instance of Spare is unbound before the call and is bound to [5] afterwards, as listmulti computed the element-wise product of the lists [1] and [5].
Now consider the following version of your predicate:
listmulti([],[],[]).
listmulti([H1|B1], [H2|B2], AllResults) :-
listmulti(B1,B2, ResultsForTheTailsOfTheLists),
Result is H1 * H2,
AllResults = [Result | ResultsForTheTailsOfTheLists].
When you call this with two lists of numbers in the first two arguments, operationally this will decompose those lists into their heads and tails, and compute the element-wise product of the tails. The result of this is a list of ResultsForTheTailsOfTheLists. The product of the heads is computed as Result. And then the results for the complete lists is just the list containing Result followed by all of the ResultsForTheTailsOfTheLists. Is this clearer?
The final twist is that in Prolog you can create lists and other data structures before you know what you will put in them. You can construct a list like this:
?- Head = a, Tail = [b, c], List = [Head | Tail].
Head = a,
Tail = [b, c],
List = [a, b, c].
but you can also construct the list first and only then bind its head and tail:
?- List = [Head | Tail], Head = a, Tail = [b, c].
List = [a, b, c],
Head = a,
Tail = [b, c].
And this is what is going on in your original definition: In the head, once you know that you are looking at two lists of numbers, you know that the result will be of the form [HeadResult | TailResults]. Having this term in the clause head builds it right away. Only later do you compute HeadResult and the TailResults through a recursive call. Overall this gives you a complete list.
I know how to do it for 2 lists:
append([],L,L).
append([H|T],L,[H|R]):-append(T,L,R).
but how to do it for 3? Without using the append for 2 lists twice.
To append lists efficiently, consider using difference lists. A difference list is a list expressed using a term with two lists. The most common representation uses (-)/2 as the functor for the term. For example, the list [1,2,3] can be expressed as:
[1,2,3| Tail]-Tail.
By keeping track of the list tail, i.e. of its open end, you can do several operations efficiently. For example, you can append an element to end of the list in O(1) by instantiating the tail:
add_to_end_of_list(List-Tail, Element, List-Tail2) :-
Tail = [Element| Tail2].
Or simply:
add_to_end_of_list(List-[Element| Tail2], Element, List-Tail2).
Let's try it:
?- add_to_end_of_list([1,2,3| Tail]-Tail, 4, Result).
Tail = [4|_G1006],
Result = [1, 2, 3, 4|_G1006]-_G1006.
Now, appending two lists is similar and also O(1). Instead of appending an element, we want to append a list of elements:
dappend(List1-Tail1, Tail1-Tail2, List1-Tail2).
For example:
?- dappend([1,2,3 | Tail1]-Tail1, [4,5,6| Tail2]-Tail2, Result).
Tail1 = [4, 5, 6|Tail2],
Result = [1, 2, 3, 4, 5, 6|Tail2]-Tail2.
I leave to you as an exercise to answer your own question using difference lists. Note that going from a difference list to a closed list, is simply a question of instantiating the open end to the empty list. For example:
?- dappend([1,2,3 | Tail1]-Tail1, [4,5,6| Tail2]-Tail2, Result-[]).
Tail1 = [4, 5, 6],
Tail2 = [],
Result = [1, 2, 3, 4, 5, 6].
However, going from a closed list to a difference list does requires you to traverse the list, which is O(n):
as_difflist([], Back-Back).
as_difflist([Head| Tail], [Head| Tail2]-Back) :-
as_difflist(Tail, Tail2-Back).
The cost of constructing the difference lists may or may not be an issue, of course, depending on how you get the initial lists and how often you will be appending lists in your application.
Hope I understood the question (and I don't think the following is more efficient than the other solutions here), but did you mean something like this?
append([],[],L,L).
append([],[H|T],L,[H|R]) :- append([],T,L,R).
append([H|T],L0,L1,[H|R]) :- append(T,L0,L1,R).
append3(Xs, Ys, Zs, XsYsZs) :-
append(Xs, YsZs, XsYsZs),
append(Ys, Zs, YsZs).
Is as efficient, as it can get. Cost is about |Xs|+|Ys| inferences. However, you might have attempted to define it like the following with about 2|Xs|+|Ys| inferences.
append3bad(Xs, Ys, Zs, XsYsZs) :-
append(Xs, Ys, XsYs),
append(XsYs, Zs, XsYsZs).
Also, termination is much better in the first case:
append3(Xs, Ys, Zs, XsYsZs)
terminates_if b(Xs),b(Ys);b(XsYsZs)
meaning that either Xs and Ys or XsYsZs needs to be known to make append3/4 terminate
... versus
append3bad(Xs, Ys, Zs, XsYsZs)
terminates_if b(Xs),b(Ys);b(Xs),b(XsYsZs)
^^^^^
for append3bad/4, where XsYsZs is not sufficient, but additionally also Xs has to be known.
I have this
initialstate(0,[],[[1,0],[2,3],[1,2],[2,3]]).
I would like to find which sublist inside the list is the same with the number 1.
And after delete the sublist who had the number one.
It would be something like that :
?- initialstate(_,_,[X,_]), initialstate(_,_,list),
delete(list,X,Newlist),assertz(initialstate(A,B,Newlist)).
I know this is wrong but i am trying to explain you what i want to do.
I want my final list to be :
initialstate(0,[],[[2,3],[2,3]]).
Edit: A new answer to incorporate CapelliC's endorsement of delete/3 and OPs further queries in the comments.
Predicate:
initial_state_without_elements(initialstate(A,B,List), Element,
initialstate(A,B,FilteredList) ):-
delete(List, Element, FilteredList).
Query:
?- initial_state_without_elements(initialstate(0,[],[[1,0],[2,3],[1,2],[2,3]]), [2,_], NewState).
NewState = initialstate(0, [], [[1, 0], [1, 2]]).
We want to take some list of lists, ListOfLists, and remove all the sublists, Ls, that contain a given Element. In general, to check if an element X is in some list List, we we can use member(X, List).
So we want a list of lists, SubListsWithout, which contains all Ls of ListOfLists for which member(Element, SubList) is false.
Here is a predicate sublists_without_elements/3, which takes a list of lists, an element, and a variable as arguments, and unifies the variable with a list of the sublists of the first which do not contain the element. This predicate uses the standard recursive technique for describing lists:
sublists_without_element([], _, []).
sublists_without_element([L|Ls], Element, SubListsWithout) :-
member(Element, L), !,
sublists_without_element(Ls, Element, SubListsWithout).
sublists_without_element([L|Ls], Element, [L|SubListsWithout]) :-
sublists_without_element(Ls, Element, SubListsWithout).
The first clause is our base case: the empty list has no sublists, regardless of the element.
The second clause is true if (1) Element is a member of L, and (2) SubListsWithout is a list of the sublists of Ls which do not contain Element. (note: *L has not been added to SubListsWithout in this clause, which means it has been excluded from the lits we are accumulating. The ! is used to prune the search path here, because once we know that an Element is a member of L, we don't want to have anything to do with L again.)
The third clause is true if L is added to SubListsWithout, and SubListsWithout contains the rest of the sublists of Ls which do not have Element as a member.
The above is one way to write your own predicate to filter a list. It is important that you be able to write and read predicates of this form, because you will see tons of them. However, you'll also want to get to know the standard libraries of your Prolog implementation. In SWI-Prolg, you can simply use exclude\3 to accomplish the above task. Thus, you could achieve your desired goal in with the following:
filter_initial_state(initial_state(A,B,List),
Element,
initial_state(A,B,FilteredList)) :-
exclude(member(Element), List, FilteredList).
You can use it thus,
?- filter_initial_state(initial_state(0,[],[[1,0],[2,3],[1,2],[2,3]]), 1, Filtered).
and prolog will reply,
Filtered = initial_state(0, [], [[2, 3], [2, 3]]).
I think you've chosen the right builtin (delete/3), but there is some detail wrong. Here is a working 'query':
?- retract(initialstate(A,B,C)), C=[[X,_]|_], delete(C,[X,_],Newlist), assertz(initialstate(A,B,Newlist)).
A = 0,
B = [],
C = [[1, 0], [2, 3], [1, 2], [2, 3]],
X = 1,
Newlist = [[2, 3], [2, 3]].
First of all: if you do a assertz without first doing a retract you'll end with having an almost duplicate of your data, and probably is not what you want. assertz stores the updated initialstate after the old one (there is asserta, but I doubt will correct the bug).
Second, note how to use pattern matching to extract the essential information:
C=[[X,_]|_]
the use of _ (i.e. an anonymous var) is essential, because allows to specify which part of the complex structure we must ignore when using it. And we must use it also to indicate to delete/3 what to match.
delete(C,[X,_],Newlist)
I am wondering how to get a nice proper looking list with the elements I have! I've been trying to look up stuff on this but none of the actual examples I've found seem to actually work
Here is one method I found on the web:
create_list(Item, List, [Item|List]).
if I run this query:
Hi = [1,2], Hey = [3,4], create_list(Hi, Hey, Output).
The result gets weird:
Output = [[1,2], 3,4]
The brackets are all wrong!
It should be:
[[1,2], [3,4]]
The brackets are all wrong! It should be:
[[1,2], [3,4]]
This is because your create_list uses [Item|List]. If you wanted brackets around [3,4] to remain in place, replace [Item|List] with [Item,List]. Of course List has incorrect meaning now, so I would rename it, as follows:
list_of_two(First, Last, [First, Last]).
This would not work for more than two items, however. Your original one rule would work, like this:
create_list([1,2],[],O1), create_list([3,4],O1,O2), create_list([5,6],O2,O3).
This produces
[[5, 6], [3, 4], [1, 2]]
in the O3 list.
In contrast with other languages, a list is a very basic datastructure in Prolog:
[] is/creates an empty list
[1] is/creates a list with a single element
[1,2,3,4,....,n] is/creates a list with n elements
[1|[2,3,4]] is/creates a list by inserting 1 in the list [2,3,4] (the result is [1,2,3,4])
So, you don't need a predicate to "create" a list: if you have n elements just put them in brackets; if the elements are generated recursively, use | to create a list with the new element. For example:
put_in_list(A1,A2,A3, L):- L = [A1,A2,A3].
alternatively:
put_in_list(A1,A2,A3, [A1,A2,A3]).
also:
generate(0, []).
generate(N, [ [N, NN]| Rest ]):-
NN is N-1,
NNN is N-2,
generate(NNN, Rest).
All in all, you should be careful with types; in your case, you have a list of numbers (let's call it X) and you want a list of lists of numbers (so this would be a list of Xs). The problem was created when you gave a list of Xs as an argument instead of an X to a predicate.
flatten([A|B],R):- (islist(A)->(flatten(A,R1),R=R1);(write(A),append([A],R1,R))), flatten(B,R1).
flatten(X,X).
islist([_|_]).
This is the code i written but i have strange problem..
I get
257 ?- flatten([1,[],2,[3],[3,[3,5]]],R).
1[]23335335
R = [1, [], 2, [3], [3, [3, 5]]] .
Although the numbers from write are not list they are appended as list:S...
There are some errors in your definition of flatten/2:
Your first clause will fail because if A is a list it will first instantiate R1 with R and then you try to unify it again with flatten(B, R1).
flatten(X,X). -> This clause leaves the list 'as is' without any flattening.
Check this other implementation:
flatten(List, Flattened):-
flatten(List, [], Flattened).
flatten([], Flattened, Flattened).
flatten([Item|Tail], L, Flattened):-
flatten(Item, L1, Flattened),
flatten(Tail, L, L1).
flatten(Item, Flattened, [Item|Flattened]):-
\+ is_list(Item).
Here we use two predicates: flatten/2 and flatten/3. The 'work' will be done in flatten/3 where the second argument will hold the intermediate flattened list.
The first clause is the base case: when we reach the empty list we are done so we instantiate the third argument with the intermediate flattened list.
The second clause deals with recursion. It flattens the first item in the list (whether it is an item or a sublist), and proceeds with the rest of the input list.
The last clause is the 'base case' for the non-lists items. It prepends the item at the beginning of the intermediate flattened list, but it only does this for items which are not lists as that case was taken care in the second clause.