How to call a list of list in Prolog for exemple I have this list :
list([[1,2,3],[4,5],[6,7]]).
I want to call my list in the element_at function :
element_at(X,[X|_],1).
element_at(X,[_|L],K) :-
element_at(X,L,K1),
K is K1 + 1.
When i call
element_at(X,list,2)
I don't have a result.
I don't have a result.
Well, you do have a result: failure. But you expected success. Here is a very general method how you can locate such errors in Prolog yourself:
If you encounter unexpected failure, simply generalize your program.
In your particular case, element_at(X,list,2) fails. Maybe it should be 3 in place of 2? Or maybe another number? There is an easy way of guessing in Prolog: Simply replace 3 by a variable! By the same token, you can remove goals in your definition. I will use * to mark those.
Here is a generalization of your program that still fails — and thus there must be an error in the remaining part:
:- op(950, fy, *).
*(_).
?- element_at(X, list, _/*2*/).
element_at(X,[_/*X*/|_],_/*1*/).
element_at(X,[_|L],K) :-
* element_at(X,L,K1),
* K is K1 + 1.
We retrieve a value from our knowledge base by a call to a predicate,
list(L)
so the whole query at the prompt is
list(L), element_at(X, L, 2).
Or define it in a source file,
my_query(X) :- list(L), element_at(X, L, 2).
Related
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
What I have to do is, write a predicate Multiplication/3, whose first argument is an integer, second argument is a list, and the third argument is the result of multiplying the integer with the list, for example:
?-Multiplication(3,[2,7,4],Result).
should return
Result = [6,21,12].
Here's my code:
Multiplication(X,[],Result).
Multiplication(X,[Head|Tail],Result) :-
Y is X*Head,
append([Result], [Y], L),
append([],L,Result), // HERE
Multiplication(X,Tail,Result).
And I get the following error:
Domain error: 'acyclic_term ' expected, found '#(lists:append([],S_1,S_1),[S_1=[S_1,1]])'
on the second append call.
If anyone knows why I receive the error, how to fix it or another way to solve this, I'm open to ideas.
Your two goals append([Result], [Y], L), append([],L,Result) are exactly the same as:
L = [Result,Y], L = Result.
or even simpler:
L = [L,Y]
which would result either in silent failure or an infinite term. Instead, your Prolog produces an error, so that you can correct your program.
In your original code:
Multiplication(X,[Head|Tail],Result) :-
Y is X*Head,
append([Result], [Y], L),
append([],L,Result), // HERE
Multiplication(X,Tail,Result).
You're getting a "cycle" because you're appending Result to something to get L, then appending something to L to get Result. That's not good. You also have a capitalized predicate name, which is a syntax error. (I assume that, since you ran your code, it wasn't capitalized in the original version.)
You're new proposed solution is overly complicated. Why do you need the 4th argument? Also, your base case for return (which is return(X, [], Result) doesn't make sense, as it has to singleton variables. The use of append/3 is overkill since recursion handles the iteration through the list elements for you.
Starting from the top, you have a common pattern in Prolog where you want to run a query on corresponding elements of two or more lists. A simple recursive solution would look something like this:
multiplication(_, [], []). % Multiplying anything by the empty list is the empty list
multiplication(M, [X|Xs], [XX|XXs]) :-
XX is M * X,
multiplication(M, Xs, XXs).
Another way to implement this kind of pattern in Prolog is with maplist/3. You can first define the query on corresponding elements:
multiply(X, Y, Product) :- Product is X * Y.
Then use maplist/3:
multiplication(M, List, Result) :-
maplist(multiply(M), List, Result).
Maplist will do a call(multiply(M), ...) on each corresponding pair of elements of List and Result.
I edited the code and came up with this:
multiplication(X,[],Result,Result).
multiplication(X,[Head|Tail],List,Result) :-
Y is X*Head,
append(List, [Y], L),
multiplication(X,Tail,L,Result).
return(X,[],Result).
return(X,L,Result) :-
multiplication(X,L,_,Result).
and the query:
return(2,[1,2],Result).
After the first run, it seems to return Result as it should be, but it runs forever.
we have a list of list think an example ?- solve([[40,A,B],[30,B],[60,A,B,C]]),label([A,B,C]). will succeed with replacing B=30,A=10 and C=20.
The constraint with this example is A+B=40, A+B+C=60 and generally every variable are in between 0 and 100. Every list must begin with a constant and it includes at least one variable.
:- use_module(library(clpfd)).
sum([],0). % if the list is empty.
sum([X|XS],Z) :-
sum(XS,Z1),
X in 0..100,
Z #= X+Z1.
solveOne([Const|Var]) :-
sum(Var,Const).
solve([]). % if the list of list is also empty
solve([First|Others]) :-
solveOne(First),
solve(Others).
I am a bit skeptic the idea of base case,facts. Because every list must include at list one variable according to constraints, on the other hand we think about the "empty list" situation.?
First, the obvious problem: you define both a solve/2 and a solve/1 predicate (solve([],0)). The ",0" is probably unwanted.
Apart from that, if you have only a constant, like [X], then solveOne succeeds only if X is zero; otherwise, it fails according to sum([],0). So, in a sense, you indirectly check that you can have at least one variable if you assume your sum is always strictly positive.
In order to explicitely check that there is effectively at least one variable, then you can modify solveOne as follows:
solveOne([Const,V1|Vars]) :-
sum([V1|Vars], Const).
#coredump answer should put you on right track. If you are interested in writing lean code, consider this more succint definition (tested in SWI-Prolog)
solve(L) :- maplist(solveOne, L).
solveOne([C|Vs]) :- Vs ins 0..100, sum(Vs, #=, C).
?- solve([[40,A,B],[30,B],[60,A,B,C]]).
A = 10,
B = 30,
C = 20.
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
...
I want a function that given a Point, and a List of points it calculates:
the absolute value of (Point - PointofList), for every point of the list.
I have this code so far, but I seem to be failing on the recursive part.
absL((X,Y),[],Result) :- Result.
absL((X,Y),[(X2,Y2)|Z], R) :- ABSX is abs(X-X2),
ABSY is abs(Y-Y2),
append([(ABSX,ABSY)], NL, R),
absL((X,Y),Z,NL).
You have defined the base case wrong.
When there are no more points in the list of points, the resulting list should be an empty list, but you are just leaving an uninstantiated variable:
So, your base case should read:
absL((_,_),[],[]).
I left the first argument with a structure using unnamed variables because the coordinates for the given point are not needed for the base case.
Your recursive clause is a bit more complex than it should. You really don't need to use append/3 to build the resulting list. You can build the list directly in the head of the clause:
absL((X,Y),[(X2,Y2)|Z], [(ABSX,ABSY)|NL]) :-
ABSX is abs(X-X2),
ABSY is abs(Y-Y2),
absL((X,Y),Z,NL).
The recursive step will add the new distance before the recursive call and just insert this values when unifying the third argument at return of the recursive call.
this clause absL((X,Y),[],Result) :- Result. attempt to call Result, at least in Prologs that accept such syntax.
since #gusbro already shows the required correction, I'll show an alternative:
absL((X,Y), L_In, L_Out) :-
maplist(absPoint((X,Y), L_In, L_Out).
absPoint((X, Y), (X2,Y2), (ABSX, ABSY)) :-
ABSX is abs(X-X2),
ABSY is abs(Y-Y2).