I've searched and strangely didn't find much on this . How can I turn a tuple of unknown length into a list in prolog?
For example:
List=[1,2,3,4], Tuple=(1,2,3,4).
When you are stuck with term conversion, it is often a good idea to get an understanding of what a term actually denotes.
You can use write_canonical/1 to get the canonical form of a term.
In your case:
?- Tuple = (1,2,3,4), write_canonical(Tuple).
','(1,','(2,','(3,4)))
Tuple = (1, 2, 3, 4).
This makes it clear that we are actually talking about compound terms of the form (A,B)—written in prefix notation as ','(A,B)—whose arguments are either integers or again such compound terms. Such terms are also called "and lists" in Prolog, and Prolog goals also have such a shape. Note in particular that these are not really "tuples", certainly not in a "first class citizen" sense, only compound terms much like any other compound terms.
Thus, we only need to reason about these 2 possible cases:
integer
term of the form (A,B).
Further, when describing lists, always consider using dcg notation for convenience.
For example:
tuple_list(I) --> { integer(I) }, [I].
tuple_list((A,B)) --> tuple_list(A), tuple_list(B).
Now we have:
?- Tuple = (1,2,3,4), phrase(tuple_list(Tuple), Ls).
Tuple = (1, 2, 3, 4),
Ls = [1, 2, 3, 4].
This solves your task of converting from such terms to lists.
However, the most general query yields no answers:
?- phrase(tuple_list(Tuple), Ls).
ERROR: Out of local stack
I leave generalizing tuples_list//1 so that it works in all directions as an exercise.
You have got two useful answers already. As mentioned, you generally don't use a "tuple" in the notation (1, 2, 3, 4): this is not a flat data structure as in say Haskell, it is a nested data structure. The Prolog way would be to use a term with arity 4, for example, quadruple(1, 2, 3, 4). The name of course doesn't matter, but usually, you use a descriptive name of some sort.
Then, to convert the arguments of a term to a list, you use the "univ" operator =.. like this:
Term =.. [Name|Arguments]
so:
?- foo(1, 2, 3, 4) =.. [foo|Args].
Args = [1, 2, 3, 4].
In the special case of tuples with two elements (pairs), the functor -/2 is commonly used. The dash is also an infix operator, so you can write 1-a instead of -(1, a). Quite a few library predicates that work on pairs expect them as -/2, for example:
?- keysort([1-c, 2-a, -(0, b), 1-a], S).
S = [0-b, 1-c, 1-a, 2-a].
tuples in Prolog are rarely used, but a quick conversion could be
list_tuple([A,B|L], (A,R)) :- list_tuple([B|L], R).
list_tuple([A,B], (A,B)). % I don't think unary tuples make sense...
?- list_tuple([1,2,3,4],T).
T = (1, 2, 3, 4) ;
false.
this doesn't work very well on 'backward mode'
?- list_tuple(L,(1,2,3,4)).
L = [1, 2, 3, 4] ;
L = [1, 2, (3, 4)] ....
you can try to place a cut to get it deterministic, I've provided clauses in order as required...
Using SWI-Prolog, "tuples" and lists can be converted using the built-in library predicate comma_list/2.
comma_list(C, [1, 2, 3]).
% C = (1, 2, 3).
comma_list((1, 2, 3), L).
% L = [1, 2, 3].
comma_list((a, foo(bar), C), [a, B, c]).
% C = c,
% B = foo(bar).
See the documentation for more usage examples.
It can be a bit tricky to search for because the documentation doesn't necessarily refer to terms like (1, 2, 3) as a "tuple", but it describes them as a "nested term over the ,/2 functor". Also provided is semicolon_list/2 which will perform the same operations with the ;/2 functor instead.
Related
I got this task in Prolog and I don't know how to approach it.
I have to write predicate expression(List,Outcome,Result) which builds an arithmetic expression using every element from List. It gives a Result which must be equal to Outcome before backtracking.
For example:
?- expression([1, 2, 3, 4], 2, X).
X = 1+ (2+ (3-4))
or
?- expression([1, 2, 3, 4, 5], 2, X).
X = 1+ ((2-3)*4+5)
I've tried something like this:
operation(A, B, A + B).
operation(A, B, A - B).
operation(A, B, A * B).
operation(A, B, A div B).
expression([],_,_).
expression([A,B,D|List],Outcome,Result) :-
operation(A,B,C),
operation(C,D,Result),
Outcome is Result.
And this works for list of three elements, but I want to use it for different sizes of list. I assume I have to use recursion, but how? And how to add the possibility of using parentheses?
Each expression is a tree. Its leaves' fringe is always the same list - the given 1st argument. Its structure reflects parenthesization. Then for each tree its nodes - when "viewed from above" - form a list of arithmetic binary operators. For each tree you need to consider all combinations of these operators.
expression( List, Result, Xpr ) :-
tree( List, T, Nodes ), % N elts in List, N-1 in Nodes
combinations( Nodes, [+,-,*,/] ), % or whatever ops you want to use
evaluate( T, Result ),
parenthesized( T, Xpr ).
combinations( Nodes, Ops ) :- % use_module( library( lambda )).
maplist( \X^(member(X, Ops)), Nodes ).
All that's left is to implement what's left to implement.
New to Ocaml, need help manipulating tuple arguments
The function takes in an argument of 3 integers and returns the reverse of it
Example: rev (5, 8, 6) = (6, 8, 5)
rev (3, 2, 1) = (1, 2, 3)
The way to access elements of a tuple in OCaml is by pattern matching.
For simple types, in fact, the pattern can appear in the place where the function argument goes.
Your function takes a 3-tuple, so it could look something like this:
let myfun (a, b, c) =
(* rest of function goes here *)
The (a, b, c) is a pattern that will match the individual elements of the tuple passed to the function.
It shouldn't be too hard to figure out how to complete the function, but don't hesitate to ask questions.
I need to construct a a predicate compare_to_predicate/3. It takes in a given predicate and list of numbers and proceeds to compare every element in the list using that predicate.
The given predicates are
- is_odd
- is_even
- greater_than(X)
For example:
?- compare_to_predicate([8,13,1,500], [is_odd], X).
X = [13, 1].
?- compare_to_predicate([8,13,1,500], [greater_than, 10], X).
X = [13, 500].
What I have come up with thus far is:
is_odd(X):- 1 is mod(X,2).
is_even(X):- 0 is mod(X,2).
greater_than(X,Y):- X<Y.
compare_to_predicate([],_,[]).
compare_to_predicate([H|Tail],Functor,[H|X]):- Term =.. [Functor,H], Term, compare_to_predicate(Tail,Functor,X).
I have a number of issues:
1)
?- compare_to_predicate([2,10,8,300],is_even,X).
will produce
X = [2, 10, 8, 300].
but
compare_to_predicate([2,10,8,301],is_even,X).
will produce
false.
I assume it has to do with the predicate encountering a number that will not return true on is_even and then terminating the whole compare_to_predicate with a false. In that case is the solution to somehow make it ignore odd numbers instead of evaluating them? If so, how would I do that?
2)
It seems that the given predicate I pass into compare_to_predicate has to have the type List as seen in
?- compare_to_predicate([8,13,1,500], [is_odd], X).
and
?- compare_to_predicate([8,13,1,500], [greater_than, 10], X).
I am currently simply passing a normal predicate into the Term. I'm not quite sure on how I'm supposed to do that.
It seems that compare_to_predicate([H|Tail],[Functor],[H|X]):- Term =.. [Functor,H], Term, compare_to_predicate(Tail,[Functor],X)
did the trick here. Finally:
3)
?- compare_to_predicate([8,13,1,500], [greater_than, 10], X).
It seems I need to make compare_to_predicate able to take in predicates with different arity as shown here. Is the solution supposed to be something like this?
(Term =.. [Functor,A]; Term=.. [Functor,A,B]).
Any help will be appreciated.
You kind of need to decide what compare_to_predicate/3 is supposed to do with values that fail the goal. I see basically three ways this can go:
It can behave as a filter, and the third argument is unified with the values in the first argument that pass.
It can behave as a for-all, and the third argument is unified with the whole list if they all pass and fails otherwise (your current behavior)
It can behave like an for-each that just applies the predicate to each item in the list and discards the result. There is no meaningful value for the third parameter in this case.
By the way, the term surgery you're doing with =../2 is not necessary; call/N will do the right thing if you do something like call(greater(10), 20), so you can just allow the user to call your predicate like this: compare_to_predicate([1,2,3,4], greater(2), X) and use call to build the goal.
Doing the first one is pretty straightforward:
filter([], _, []).
filter([X|Xs], P, Result) :-
filter(Xs, P, Xs1),
(call(P, X) -> Result = [X|Xs1] ; Result = Xs1).
Doing the second one is also pretty straightforward:
forall([], _, []).
forall([X|Xs], P, [X|Xs]) :- call(P, X), forall(Xs, P, Xs).
Doing the third one is not terribly hard:
foreach([], _).
foreach([X|Xs], G) :- once(call(G, X) ; true), foreach(Xs, G).
Note: Near complete beginner to logic programming
I need to compare two lists of integers and figure out if one is greater, greater-equal, or they are both equal.
For example:
compare_list([1, 2, 3], [1, 2, 4], C).
C = greater,
C = greater-equal.
compare_list([1, 2, 3], [1, 2, 4], C).
C = equal.
So far the closest I have been able to get has been...
compare_list([],[],_).
compare_list([X|XS],[Y|YS],C):-
X > Y,
compare_list(XS,YS,C),
C = 'greater'.
compare_list([X|XS],[Y|YS],C):-
X >= Y,
compare_list(XS,YS,C),
C = 'greater-equal'.
compare_list([X|XS],[Y|YS],C):-
X == Y,
compare_list(XS,YS,C),
C = 'equal'.
Now that obviously doesn't work as needed because it is always comparing the first element of each list and seeing if the C value holds for all of the values. However I cannot think of a way to make it work as intended.
Edit:
The earlier a value is in a list, the more important it is. So [2,2] > [1,3] > [1,2]
Tips would be appreciated. Thanks.
Edit:
Solved by waiting until the end to assign C to anything.
In your solution you use (>)/2, (>=)/2 and (==)/2. The first two will evaluate their arguments as arithmetic expressions prior to a comparison. And (==)/2 will compare due to term order. You will have to decide for one of them or another term order. But you cannot mix them.
The second remark is that you would also need something as 'less' as a result.
If two elements already compare as (<)/2, there is no need for further comparison.
Also, equality can only be stated in the fact, but not before.
Consider to use the built-in predicate `compare/3`:
?- compare(R, [1, 2, 3], [1, 2, 4]).
R = (<).
?- compare(R, [1, 2, 3], [1, 2, 3]).
R = (=).
Should you write your own comparison predicate, better use the very same argument order and the same terms as result. That is, <, =, and >. It does not make a lot of sense, to expect >= to be a result. After all, two identical lists would then have three different solutions =<, =, >=.
From your description, it is not clear to me what you expect, if both lists are of different length.
According to your definition of "greater" there is no need to continue the recursion after you find that X>Y. If you reach the end of the recursion (as chac said) you'll know that the two lists are equal.
To get "greater-equal" you should instead check that X is not less than Y. You may think of this as "if X is less than Y than fail". Take a look at negation as failure.
You can stop comparing at the first ineguagliance. If you reach the end of (both) lists, that means lists are equals.
The following code will check whether two list are equal or not
is_equal([],[]).
is_equal([H1|T1],[H2|T2]):- H1=:=H2,is_equal(T1,T2).
I want to define an operator "++>" in a way so that typing "a ++> b" will make a list of [a,b].
I've written the following code, but it doesn't appear to do the job.
++>(X,Y) :-
[X,Y].
:- op(500,xfy,++>).
:- op(500,xfy,++>).
++>(X,Y,[X,Y]).
And use it like
?- ++>(1,2,X).
X = [1, 2].
Actually, Prolog is not oriented calculations, so operators is just synonyms to the terms.
You want a term\3, where one element is list of two another. So, you can't use 2-placed operator in that case. Btw, you can't use is in this situation, because it used only in arithmetic cases.
Does this work for you:
++>((X,Y),Z) :-Z= [X,Y].
:- op(500,xfy,++>).
[a,b,c] is just syntactic sugar for '.'(a,'.'(b,'.'(c)))). So you may define your operator just the same and write a conversion predicate:
:- op(500,xfy,'++>').
convert('++>'(A,B),[A|R]) :-
convert(B,R).
convert(Any,[Any]).
Example:
| ?- X = 1++>2++>3, convert(X,Y).
X = 1++>2++>3
Y = [1,2,3] ?
yes