Prolog, List of lists contains another list exactly - prolog

What I basically want to achieve is, that given a list of lists A, I want a predicate that checks if the elements of a list B are exactly contained in list A.
So for example:
A = [[1,2],[3,4],[5],[]]
B = [1,2,3,4,5]
and
A = [[1,2],[3,4],[5],[]]
B = [2,5,3,4,1]
Would result to true, but
A = [[1,2],[3,4],[5],[]]
B = [1,2,3,4]
and
A = [[1,2],[3,4],[5],[]]
B = [1,2,3,4,5,6]
would both result to false.
is this possible in prolog?
Exactly means:
Order doesn't matter, it just has to contain all the elements.
Also, imagine that the B list doesn't contain duplicates.
So if A would contain duplicates, we should get false as a result.

The trivial answer:
?- flatten([[1,2],[3,4],[5],[]], [1,2,3,4,5]).
true.
?- flatten([[1,2],[3,4],[5],[]], [1,2,3,4]).
false.
?- flatten([[1,2],[3,4],[5],[]], [1,2,3,4,5,6]).
false.
Or,
foo(A, B) :- % because I don't know how to call it
flatten(A, B).
If you are talking about sets:
bar(A, B) :-
flatten(A, A_flat),
sort(A_flat, A_sorted),
sort(B, A_sorted).
You can use msort/2 if you don't want to remove duplicates.
If the question is, "how do I implement flatten/2", you can find several answers on SO.

Related

Function to find a list in prolog

I am new to Prolog and I am trying to write a function that finds a list that follows some rules.
More specifically, given two numbers, N and K, I want my function to find a list with K powers of two that their sum is N. The list must not contain each power but the total sum of each power. For example if N=13 and K=5, I want my list to be [2,2,1] where the first 2 means two 4, the second 2 means two 2, and the third 1 means one 1 (4+4+2+2+1=13). Consider that beginning from the end of the list each position i represents the 2^i power of 2. So I wrote this code:
sum2(List, SUM, N) :-
List = [] -> N=SUM;
List = [H|T],
length(T, L),
NewSUM is SUM + (H * 2**L),
sum2(T, NewSUM, N).
powers2(N,K,X):-
sum2(X,0,N),
sum_list(X, L),
K = L.
The problem is:
?- sum2([2,2,1],0,13).
true.
?- sum2([2,2,1],0,X).
X = 13.
?- sum2(X,0,13).
false.
?- powers2(X,5,[2,2,1]).
X = 13.
?- powers2(13,5,[2,2,1]).
true.
?- powers2(13,X,[2,2,1]).
X = 5.
?- powers2(13,5,X).
false.
In the cases, X represents the list I expected the output to be a list that follows the rules and not false. Could you help me to find how can I solve this and have a list for output in these cases?
The immediate reason for the failure of your predicate with an unbound list is due to your use of the -> construct for control flow.
Here is a simplified version of what you are trying to do, a small predicate for checking whether a list is empty or not:
empty_or_not(List, Answer) :-
( List = []
-> Answer = empty
; List = [H|T],
Answer = head_tail(H, T) ).
(Side note: The exact layout is a matter of taste, but you should always use parentheses to enclose code if you use the ; operator. I also urge you to never put ; at the end of a line but rather in a position where it really sticks out. Using ; is really an exceptional case in Prolog, and if it's formatted too similarly to ,, it can be hard to see that it's even there, and what parts of the clause it applies to.)
And this seems to work, right?
?- empty_or_not([], Answer).
Answer = empty.
?- empty_or_not([1, 2, 3], Answer).
Answer = head_tail(1, [2, 3]).
OK so far, but what if we call this with an unbound list?
?- empty_or_not(List, Answer).
List = [],
Answer = empty.
Suddenly only the empty list is accepted, although we know from above that non-empty lists are fine as well.
This is because -> cuts away any alternatives once it has found that its condition is satisfied. In the last example, List is a variable, so it is unifiable with []. The condition List = [] will succeed (binding List to []), and the alternative List = [H|T] will not be tried. It seems simple, but -> is really an advanced feature of Prolog. It should only be used by more experienced users who know that they really really will not need to explore alternatives.
The usual, and usually correct, way of implementing a disjunction in Prolog is to use separate clauses for the separate cases:
empty_or_not([], empty).
empty_or_not([H|T], head_tail(H, T)).
This now behaves logically:
?- empty_or_not([], Answer).
Answer = empty.
?- empty_or_not([1, 2, 3], Answer).
Answer = head_tail(1, [2, 3]).
?- empty_or_not(List, Answer).
List = [],
Answer = empty ;
List = [_2040|_2042],
Answer = head_tail(_2040, _2042).
And accordingly, your definition of sum2 should look more like this:
sum2([], SUM, N) :-
N = SUM.
sum2([H|T], SUM, N) :-
length(T, L),
NewSUM is SUM + (H * 2**L),
sum2(T, NewSUM, N).
This is just a small step, however:
?- sum2(X, 0, 13).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [9] _2416 is 0+_2428* ...
ERROR: [8] sum2([_2462],0,13) at /home/gergo/sum.pl:5
ERROR: [7] <user>
You are trying to do arithmetic on H, which has no value. If you want to use "plain" Prolog arithmetic, you will need to enumerate appropriate values that H might have before you try to do arithmetic on it. Alternatively, you could use arithmetic constraints. See possible implementations of both at Arithmetics in Prolog, represent a number using powers of 2.

Prolog Sorting List By Rule Position

I am new to Prolog and for the following program:
place(Store,2,a).
place(Store,1,b).
place(Store,3,d).
place(Store,4,c).
placeSort(S,List):- findall(L,place(S,N,L),List).
output: List = [a, b, d, c].
By using placeSort(S,List) , I can find all the elements(a,b,c,d) that contains S (Store).
However what I want to achieve here is to sort the Position of a,b,c,d by using N, however I dont know how to do so as using sort will just sort it out by alphabetical order
placeSort(S,NewList):- findall(L,place(S,N,L),List),sort(List,NewList).
output: List = [a, b, c, d].
what I want to achieve : List = [b,a,d,c]
**I know by using placeSort(S,NewList):- findall([N,L],place(S,N,L),List),sort(List,NewList).
it will return a list of lists sorted by numbers.
output : List = [[1, b], [2, a], [3, d], [4, c]].
but im not sure how to take away the numbers and just take the alphabets instead.
Any help would be greatly appreciated.
SWI-Prolog offers the interesting builtin order_by/2, filling the gap traditional Prolog suffers when compared to SQL, with library(solutionsequences):
?- order_by([asc(X)],place(P,X,W)).
X = 1,
W = b ;
X = 2,
W = a ;
...
So you can avoid full list construction.
The easiest way to do this is to use setof/3 (which sorts by term) and pick a term form that works for you on your sort. In this case, you can collect terms of the form N-X where they satisfy, place(_, N, X):
setof(N-X, place(S,N,X), OrderedList). % Assuming `S` is bound
This will result in:
OrderedList = [1-b, 2-a, 3-d, 4-c]
Then you can use maplist/3 to get your list by defining a simple mapping:
foo(_-X, X).
maplist(foo, OrderedList, List).
This will then give you just the elements you want.
Your complete predicate would look like:
foo(_-X, X).
placeSort(S, List) :-
setof(N-X, place(S,N,X), OrderedList),
maplist(foo, OrderedList, List).
Obviously, you'd choose sensible names for your facts, predicates, and variables. My names (foo, List, OrderedList, S, N, X) are not sufficient, in my opinion, for an application but I am not familiar with your actual problem domain, so this is just for illustration purposes.
As an aside, note that in your facts Store is a variable, so that's not particularly meaningful in the facts. I kept your use of S in your predicate, but it's unclear to me how you really intend to use it.

Prolog combining predicates

Just a small question about Prolog. Say I have used the built in predicate findall/3 to obtain a list and used the variable X as my output.
I'm wondering how I could then use this list in another predicate such as last/2 to find the last element of this list. If you could include a small example too that would help greatly.
First of all, since Prolog aims to be a logic programming programming language, there is nu such thing as output variables.
Nevertheless, say you know a variable X is bounded after a certain predicate and you intend to use this value when calling a new predicate, you can use Prolog's logical "and" ,/2. I'm putting "and" between quotes because this and differs sometimes from the natural understanding of how "and" in natural language behaves.
You can thus use a predicate:
findall(A,foo(A),X),last(X,L).
To first find all occurences of foo/1, extract the variable A, put these into a list X and finally get the last/2 element of X.
You can then for instance use this in a defined predicate:
last_foo(L) :-
findall(A,foo(A),X),
last(X,L).
If you run this for instance with:
foo(a).
foo(9).
foo(b).
The results are:
?- foo(A).
A = a ;
A = 9 ;
A = b.
and:
?- findall(A,foo(A),X).
X = [a, 9, b].
Now the result to obtain the last is:
?- findall(A,foo(A),X),last(X,L).
X = [a, 9, b],
L = b.
or:
?- last_foo(L).
L = b.

Checking that a list contains only zeros

I have been given a question in my assignment that asks to write a Prolog program that takes as input a list of numbers and succeeds if the list
contains only 0s.
I am having trouble on how to make the program search for zeroes. For example, a query like:
?- zero([0,0,0,0]).
Should give us true and it should return false whenever there's a number other than zero in it.
Usually, one would not define a proper predicate for this, but rather use maplist/2 for the purpose:
..., maplist(=(0), Zs), ...
To give a concrete example:
?- Zs =[A,B,C], maplist(=(0), Zs).
This query corresponds to:
?- Zs = [A,B,C], call(=(0), A), call(=(0), B), call(=(0), C).
or even simpler:
?- Zs = [A,B,C], 0 = A, 0 = B, 0 = C.
If you want to define this as a separate predicate, remember to use a good name for it. Each element of the list is a zero, and the relation describes the entire list of such zeros. The convention for lists in this case is to use the plural word. Thus zeros/1:
zeros([]).
zeros([0|Zs]) :-
zeros(Zs).
why are you asking us to do your homework for you?
anyway, it's very simple recursion. something like:
zero([]).
zero([0|T]) :- zero(T).
just keep peeling of zero's until your list is empty. it isn't so hard ;)

Prolog - get the first list from a list of lists

I've got a list consisting of smaller lists inside of it, each list consisting of 2 items:
[[a,1],[b,2],[c,3]]
I'm using a function called take(1,L,R) to take the first item from list L and return the item R. The code for the take function is here:
take(0,X,X).
take(N,[H|T],[H|R]):-
N>0, M is N-1,
take(M,T,R).
At the moment a run may look like this:
1 ?- take(1,[[a],[b],[c]],Taken).
Taken = [[a], [b], [c]]
Which is the same as the input! This is the same for a "regular" 1-level-depth list:
2 ?- take(1,[a,b,c],Taken).
Taken = [a, b, c]
Question:
The question for you is how can I make the result look like:
1 ?- take(1,[[a],[b],[c]],Taken).
Taken = [a]
I want to return the first N items of the list I send it.
Your base case take(0, X, X). is doing exactly what it says -- given any value X, the result is X. What I think you were trying to say is take(1, [H|T], H). (which yields the first element of a list).
What I think you're actually after is take(0, _, [ ]). which yields an empty list when "taking" 0 items from any list. This works well with your existing recursive case.
You say that you want to get the "first N items of the list" -- such a result must be stored in a list of N items. It follows that take(1, [a, b, c], Taken) would yield Taken = [a], not Taken = a. Similarly, take(1, [[a], [b], [c]], Taken). would yield Taken = [[a]].. To special-case the take(1, ...) form to return the first item only (without it being wrapped in a list) would break your recursion.

Resources