Appending lists in Prolog with functor - prolog

I am trying to use Prolog's append and length predicates for the first time in order to split a list, and I believe it requires a recursive solution. I am new to Prolog, and would like some help with this starter problem! :)
Here is the expected code output:
?- splits([1,2,3],S).
S = [1]/[2, 3] ;
S = [1, 2]/[3] ;
false.
It takes a list and splits it, but it does so by creating a structure with the functor /, this is what confuses me so far... I know that I need to use append for this, but how would one do so?
Here is my code so far:
splits([H | T], S) :-
length(T, len), len > 0,
It will run until the tail of the list is empty, and then stop, but I can't quite figure out how to add in the append function or make it recursive... Could someone give me a tip? :)

I would say that you are almost at a working implementation with your remark that append/3 can be used for splitting lists. This is indeed what append/3 in the instantiation (-,-,+) does.
The only added requirement that seems to occur in your question is to exclude cases in which either of the splits is empty. This can be achieved by checking for inequivalence between terms using \==/2.
This results in the following code:
splits(List, X/Y):-
append(X, Y, List),
X \== [],
Y \== [].
PS: Notice that your use of len in your code snippet is wrong, since len is not a Prolog variable but an atom. Handing an atom to the second argument of length/2 produces a type error, and an arithmetic error in len > 0 (provided that len is not defined as a function). (Both observations relate to SWI-Prolog.)
Hope this helps!

Here is a recursive approach:
splits([A,B|T], [A]/[B|T]).
splits([A|T], [A|R]/S) :-
splits(T, R/S).
The first clause provides the base case of splitting a list with at least 2 elements ([A,B|T]) into [A]/[B|T] (it just splits out the first element).
The second clause says that [A|R]/S is the split of [A|T] if R/S is the split of T. So it will "generate" the other solutions recursing down to the base case. If the first list has only two elements, the base case will be successful, and backtrack to the recursive case will fail on the first try (which is what you want - no more solutions to that case) because the recursive case only succeeds when the first list has 3 or more elements (A plus the two enforced on T in the recursive query).
| ?- splits([1], S).
no
| ?- splits([1,2], S).
S = [1]/[2] ? ;
no
| ?- splits([1,2,3], S).
S = [1]/[2,3] ? ;
S = [1,2]/[3] ? ;
no
...

Related

List with if - plus and minus

I should create a list with integer.It should be ziga_arnitika(L,ML).Which take L list (+) integer and will return the list ML only (-) integer the even numbers of list L.
Warning:The X mod Y calculates X:Y.
Example: ziga_arnitika([3,6,-18,2,9,36,31,-40,25,-12,-5,-15,1],ML).
ML =[-18,-40,-12]
i know for example with not list to use if but not with lists,what i did is..:
something(12) :-
write('Go to L).
something(10) :-
write('Go to Ml).
something(other) :-
Go is other -10,
format('Go to list ~w',[ML]).
You want to compute a list with elements satisfying some properties from a given list. Lists in Prolog have a very simple representation. The empty list is represent by []. A non-empty list is a sequence of elements separated by a comma. E.g. [1,2,3]. Prolog also provides handy notation to split a list between its head (or first element) and its tail (a list with the remaining arguments):
?- [1,2,3] = [Head| Tail].
Head = 1,
Tail = [2, 3].
Walking a list (from its first element to its last element) can be done easily using a simple recursive predicate. The trivial case is when a list is empty:
walk([]).
If a list is not empty, we move to the list tail:
walk([Head| Tail]) :- walk(Tail).
However, if you try this predicate definition in virtually any Prolog system, it will warn you that Head is a singleton variable. That means that the variable appears once in a predicate clause. You can solve the warning by replacing the variable Head with an anonymous variable (which we can interpret as "don't care" variable). Thus, currently we have:
walk([]).
walk([_| Tail]) :- walk(Tail).
We can try it with our example list:
?- walk([1,2,3]).
true.
Prolog being a relational language, what happens if we call the walk/1 predicate with a variable instead?
?- walk(List).
List = [] ;
List = [_4594] ;
List = [_4594, _4600] ;
List = [_4594, _4600, _4606]
...
Now back to the original problem: constructing a list from elements of other list. We want to process each element of the input list and, if it satisfies some property, adding it to the output list. We need two arguments. The simple case (or base case) is again when the input list is empty:
process([], []).
The general case (or recursive case) will be:
process([Head| Tail], [Head| Tail2]) :-
property(Head),
process(Tail, Tail2).
assuming a predicate property/1 that is true when its argument satisfies some property. In your case, being a even, negative integer. But not all elements will satisfy the property. To handle that case, we need a third clause that will skip an element that doesn't satisfy the property:
process([Head| Tail], List) :-
\+ property(Head),
process(Tail, List).
The \+/1 predicate is Prolog standard negation predicate: it's true when its argument is false.
Let's try our process/2 predicate it by defining a property/1 predicate that is true if the argument is the integer zero:
property(0).
A sample call would then be:
?- process([1,0,2,0,0,3,4,5], List).
List = [0, 0, 0] ;
false
We have successfully written a predicate that extracts all the zeros from a list. Note that our query have a single solution. If we type a ; to ask for the next solution at the prompt, the Prolog top-level interpreter will tell us that there are no more solutions (the exact printout depends on the chosen Prolog system; some will print e.g. no instead of falsebut the meaning is the same).
Can you now solve your original question by defining a suitable property/1 predicate?
Update
You can combine the two recursive clauses in one by writing for example:
process([Head| Tail], List) :-
( % condition
property(Head) ->
% then
List = [Head| Tail2],
process(Tail, Tail2)
; % else
process(Tail, List)
).
In this case, we use the Prolog standard if-then-else control construct. Note, however, that this construct does an implicit cut in the condition. I.e. we only take the first solution for the property/1 predicate and discard any other potential solutions. The use of this control construct also prevents using the process/2 predicate in reverse (e.g. calling it with an unbound first argument and a bound second argument) or using it to generate pairs of terms that satisfy the relation (e.g. calling it with both arguments unbound). These issues may or may not be significant depending on the property that you're using to filter the list and on the details of the practical problem that you're solving. More sophisticated alternatives are possible but out of scope for this introductory answer.

Prolog, how should I construct a list of list to a single list?

I want to construct a list of list to interleave each other to a single list like: coon([[1,4],[2,5],[3,6]], X) should return X=1,2,3,4,5,6. and there is a condition that each sublist should only have the same length, otherwise, it should fail such as [[q,r,y],[a,e],[c,g,t],X] shouid fail, and coon([A,B,C],[q,w,e,r,t,y]) should only return one solution, that is A=[q,r],B=[w,t],C=[e,y].
my recent approach is.
conns([],[]).
conns([[Head|Tail]|X],[Head|Y]):-
append(X,[Tail],X2),
conns(X2,Y).
conns([[]|T],A):-
conns(T,A).
It gives me multiple solutions when I try coon([A,B,C],[q,w,e,r,t,y]).
I have been trying hours to figure it out but all failed. How should I return the single list to each sub-lists that contain the same length?
Thank you so much!
:- use_module(library(clpfd),[transpose/2]).
connsx(Xss, Xs) :-
transpose(Xss, XssT),
append(XssT, Xs).
The problem you are having is with this predicate clause:
conns([[]|T],A):-
conns(T,A).
This allows solutions more general than you are wanting to define. Specifically, if I understand the problem correctly, the first argument to conns should always be a list whose elements are lists all of equal length. That would mean that if [[]|T] is the first argument and you expect conns([[]|T], A) to succeed, then T should also look like [[]|R] or []. That is, it should be a (possibly empty) list of empty lists.
If you revise the empty list case according to this constraint, your solution will work:
% The case where the first argument consists of non-empty lists
conns([[Head|Tail]|X], [Head|Y]):-
append(X, [Tail], X2),
conns(X2, Y).
% Base case in which first argument is a list of empty lists
conns([], []).
conns([[]|T], []) :-
conns(T, []).
Now when you run the query, you get this:
| ?- conns([[1,4],[2,5],[3,6]], R).
R = [1,2,3,4,5,6] ? ;
no
| ?-
As well as:
| ?- conns([A,B,C], [q,w,e,r,t,y]).
A = [q,r]
B = [w,t]
C = [e,y] ? a
no
| ?-
This solution does leave a choice point, which I'll leave as an exercise to eliminate if you wish.

Prolog return a list which contains only elements which are equal to head of the list

Hello I would like to ask a doubt I have with the following code:
principio([],[]).
principio([H],[H]).
principio([H,_|_],[H]).
principio([H,H|C],P) :-
principio([H|C],R),P=[H|R].
I would like a way to get from:
?- principio([222,333,101,202,12,222,13,222],X).
X = [222,222,222]
But in this moment I get just the head:
X = [222]
So, to keep it clear I'd like: all successive occurrences of the first element as a list.
My doubt is what does this assignment P=[H|R] why not to put just:
principio([H,H|C],P) :-
principio([H|C],P)
Also, how would you try to modify this to get the result I asked for?
Thank you
Here is two ways how you can narrow down the problem. 1st, start from an unexpectedly failing query. 2nd, start from a query that should fail but rather succeeds.
1st Diagnose unexpected incompleteness
Determine a most specific failing query
?- principio([222,333,101,202,12,222,13,222],[222,222,222]).
false.
Generalize the query
... as much as possible. I could do this manually, or I could let Prolog do the work for me. Here I use library(diadem):
?- use_module(diadem).
true.
?- principio([222,333,101,202,12,222,13,222],[222,222,222]).? Gen.
Gen = principio([222, 333|_], [_, _|_])
; Gen = (dif(A100, B100), principio([A100, B100|_], [_, _|_]))
; ... .
In other words: Not only does your original query fail, but also this generalization fails! Here, we only insist that the first two elements are different, and that the resulting list contains at least two elements — no matter which!
?- dif(X, Y), principio([X,Y|_],[_,_|_]).
Generalize your program
:- op(950, fy, *).
* _P_0.
principio([], _/*[]*/).
principio([_H], _/*[H]*/).
principio([H,_|_],[H]).
principio([H,H|C],P) :-
* principio([H|C],R),
* P=[H|R].
The error must reside in the little remaining part of your program. No need to read any further!
The problem is that for a list starting with two different elements you only have the clause principio([H,_|_],[H]).. So this part has to be generalized somehow.
2nd Diagnose unexpected unsoundness
Another way of finding the error would be to start with the unexpected solution:
?- principio([222,333,101,202,12,222,13,222],[222]).
true. % incorrect !!
And then reduce the size of the query as much as possible.
?- principio([222,222],[222]).
true. % incorrect !!
Now, specialize your program inserting false as long as above query succeeds:
principio([],[]) : - false.
principio([H],[H]) :- false.
principio([H,_|_],[H]).
principio([H,H|C],P) :- false,
principio([H|C],R),
P=[H|R].
The remaining visible part is the culprit! We have to revise it. What it says is:
Any list starting with two elements corresponds to the list with the first element only.
principio([],[]).
principio([H],[H]).
principio([H,D|Xs], [H|Hs]) :-
dif(H,D),
principio([H|Xs],[H|Hs]).
principio([H,H|Xs],[H|Hs]) :-
principio([H|Xs],Hs).
In addition to the very nice answer provided by #false (+s(0)), I would point out the possibility to use DCGs for the task. They usually yield easily readable code when describing lists (see comments beside the grammar rules):
principio([H|T],Hs) :-
phrase(heads([H|T],H),Hs).
heads([],_H) --> % in the empty list
[]. % there's no element matching H
heads([H|Xs],H) --> % if the head of the list matches H
[H], % it's in the list
heads(Xs,H). % same for the tail
heads([X|Xs],H) --> % if the head of the list is
{dif(X,H)}, % different from H it's not in the list
heads(Xs,H). % same for the tail
Thus your example query yields the desired result:
?- principio([222,333,101,202,12,222,13,222],X).
X = [222,222,222] ? ;
no

Predicate about a list of lists

I'm trying to create a predicate that receives a list of lists and returns a list of lists containing all the unitary lists (lists whose length is 1) from the first list, however it is not working. This is what I created:
elimina_listas_nao_unitarias_lista_de_listas([[A]|T],N_List):-
length([A], 1),
N_List is [H|N_List_T],
elimina_listas_nao_unitarias_lista_de_listas(T, N_List_T).
elimina_listas_nao_unitarias_lista_de_listas([[A]|T], N_List):-
length([A], X),
X > 1,
elimina_listas_nao_unitarias_lista_de_listas(T, N_List2).
Thi is what it should do:
elimina_listas_nao_unitarias_lista_de_listas([[1,2],[1,2,3],[3]], [3])
elimina_listas_nao_unitarias_lista_de_listas([[1,2],[1,2,3],[3,4,5]], [])
It is retuning false currently everytime
Let's take a look at your first rule. The first goal always succeeds, since you are asking if a list with a single element is of length 1. Just try it at the prompt:
?- length([A], 1).
true
Instead, you probably want to have a variable without the brackets in the head of the first list (e.g. [L|Ls]) and ensure that it is a list of length 1:
?- length(L,1).
L = [_A]
The same goes for the first list in the head of your second rule and its first goal. In your second goal you are trying to evaluate [H|N_List_T] as an arithmetic expression with is/2 such that N_List holds the value. Besides the fact that this doesn't make sense, you can try that at the prompt and see how this goal can't succeed:
?- N_List is [H|N_List_T].
ERROR!!
TYPE ERROR- string must contain a single character to be evaluated as an arithmetic expression: expected evaluable term, got [_131245|_131246]
Instead, you want to unify the two terms:
?- N_List = [H|N_List_T].
N_List = [H|N_List_T]
However, you can get rid of this goal entirely if you write [H|N_List_T] as the second argument in the head of the rule. Additionally, you might want the unitary list L in the head of the second list instead of the variable H. Furthermore you are missing a case, namely the first list being []. In that case the second list is empty as well, since the empty list clearly does not contain any unitary lists. Finally, I would note that it might enhance the readability of your code if you picked a somewhat simpler and more declarative name, say listas_unitarias/2. Putting all this together, you might end up with a predicate like this:
listas_unitarias([],[]).
listas_unitarias([L|Ls],[L|Ss]) :-
length(L,1),
listas_unitarias(Ls,Ss).
listas_unitarias([L|Ls],Ss) :-
length(L,X),
dif(X,1),
listas_unitarias(Ls,Ss).
Your second example query yields the desired result
?- listas_unitarias([[1,2],[1,2,3],[3,4,5]],U).
U = []
For your first example query the result is slightly different:
?- listas_unitarias([[1,2],[1,2,3],[3]], U).
U = [[3]] ? ;
no
The only unitary list is in a list itself. That would make more sense, since the first argument might contain more than one such list. Consider the following case:
?- listas_unitarias([[1],[2,3],[4],[]],U).
U = [[1],[4]] ? ;
no
However, if you meant to get the unitary lists one at a time, the predicate would look slightly different:
listas_unitarias2([L|_Ls],L) :-
length(L,1).
listas_unitarias2([_L|Ls],U) :-
listas_unitarias2(Ls,U).
As would the results of the queries:
?- listas_unitarias2([[1,2],[1,2,3],[3]], U).
U = [3] ? ;
no
?- listas_unitarias2([[1],[2,3],[4],[]],U).
U = [1] ? ;
U = [4] ? ;
no
Especially your second example query: It would fail instead of producing the empty list as a solution:
?- listas_unitarias2([[1,2],[1,2,3],[3,4,5]],U).
no
?- listas_unitarias2([[1,2],[1,2,3],[3,4,5]],[]).
no
EDIT: As pointed out by #false in the comments the combined use of length/2 and dif/2 in the third rule doesn't terminate for [_,_|_] so the query
?- listas_unitarias([[1],[_,_|_],[2],[3,4]],U).
U = [[1],[2]] ? ;
U = [[1],[2]] ? ;
...
does not terminate as well. However, it is reasonable to expect termination in this case, since a list headed by two elements certainly can't be unitary. So, instead of using length/2 you might consider describing the four cases that cover all possibilities. 1) If the first list is empty so is the second list. 2) If the head of the first list is [] it's not in the second list. 3) If the head of the first list is [A] it is in the second list. 4) If the head of the first list has at least two elements it's not in the second list.
listas_unitarias([],[]). % case 1)
listas_unitarias([[]|Ls],Ss) :- % case 2)
listas_unitarias(Ls,Ss).
listas_unitarias([[A]|Ls],[[A]|Ss]) :- % case 3)
listas_unitarias(Ls,Ss).
listas_unitarias([[_,_|_]|Ls],Ss) :- % case 4)
listas_unitarias(Ls,Ss).
With this version the above query terminates after finding the only solution:
?- listas_unitarias([[1],[_,_|_],[2],[3,4]],U).
U = [[1],[2]]
The other queries from above yield the same results:
?- listas_unitarias([[1,2],[1,2,3],[3,4,5]],U).
U = []
?- listas_unitarias([[1,2],[1,2,3],[3]], U).
U = [[3]]
?- listas_unitarias([[1],[2,3],[4],[]],S).
S = [[1],[4]]

PROLOG: Check if first list contains 3 times less of each element than second list

I need to check if each element in second list has 3 times more instances then the same element in the first list. My function returns false all the time and I don't know what I'm dong wrong.
Here is the code:
fourth(_,[ ]).
fourth(A,[HF|TF]) :-
intersection(A, HF, NewA),
intersection(TF, HF, NewB),
append(HF, NewB, NewT),
append(NewA, NewA, NewAA),
append(NewA, NewAA, NewAAA),
length(NewAAA) == length(NewT),
select(HF, TF, NewTF),
fourth(A, NewTF).
Example:
?- fourth([1,2,3], [1,1,1]).
true.
?- fourth([1,2,3], [1,1,1,1]).
false.
?- fourth([1,2,3], [1,1]).
false.
?- fourth([1,2,2,3], [1,1,2,2,1,2,2,2,2]).
true.
I would make myself a select/3 predicate: select(X,From,Left), and then for each elt of a first list I'd call it three times with same first argument on a second list, progressively passing it forward, getting me a final Left3 without the three occurences of X; iand I'd do that for each elt of a first list. Then if I'd succeed and end up with an empty list, that means it had exactly three times each elt from the first list.
Your code seems needlessly complicated. It also contains bugs where you use HF instead of the list [HF].
So what's the logic you want to implement?:
take the next element from the second list (leaving the tail)
check if it's in the first list, and if it is, remove it (else fail)
remove it two more times from the tail of the second list
and this gives:
fourth(_,[ ]).
fourth(A,[HF|TF]) :-
once(select(HF, A, AR)), % using once/1 to avoid choicepoints
once(select(HF, TF, TF1)),
once(select(HF, TF1, TFR)),
fourth(AR, TFR).
Here is your code with suggestions on why it fails :
fourth(_,[]).
fourth(A,[HF|TF]) :-
intersection(A, HF, NewA),
intersection(TF, HF, NewB),
It's not intersection/3 that you want to use, for two reasons :
1) it doesn't filter only HF in A.
2) it fails if you call it with an element, so at least use [HF] instead
of HF
Instead, use include/3 : include(=(HF), A, NewA). See SWI-pl doc for more info.
append(HF, NewB, NewT),
append(NewA, NewA, NewAA),
append(NewA, NewAA, NewAAA),
Use of append/2 is better, especially for your NewAAA list.
length(NewAAA) == length(NewT),
You can't compare lengths like that. First, length/1 doesn't exist in
built-in swi-pl predicates. Instead, compare directly the lists or use
length/2 twice and then compare the results.
select(HF, TF, NewTF),
fourth(A, NewTF).
Only removing once HT in TF will cause your algorithm to fail. You need
to remove all the occurrences of HT in TF, with subtract/3 for example...
If you want a working solution respecting your original work, I'll add it, so feel free to ask, but as it was tagged homework I'll let you those working leads first...
% Blocks in our "block world"
%
% b3
% b4 b7
% b1 b5 b8
% b2 b6 b9
%==============
% Block Stacking
on(b1,b2).
on(b3,b4).
on(b4,b5).
on(b5,b6).
on(b7,b8).
on(b8,b9).
% Stack order
left(b2,b6).
left(b6,b9).
% Generalize "above"
above(Above,Below) :- on(Above,Below).
above(Above,Below) :- on(Above,AnyBlock), above(AnyBlock,Below).
% isLeft(X,Y) resolves to true if X is a block left of any block Y.
% isLeft/2 simply invokes leftOf/2 followed by a cut (!) to guarantee that
% only one result is generated.
%
% For Example: isleft(b1,b7) produces true
% isleft(b2,b6) produces true
% isleft(b4,b5) produces false.
% isleft(b9,b3) produces false.
isLeft(X,Y) :- leftOf(X,Y), !.
% Show an implementation of leftOf below. The implementation will involve a
% few cases (like the above predicate above), but can be completed using only the
% provided left and above predicates.

Resources