How can I substract in prolog the elements from this structure: s(1, [[],[],[],[]] )? I need the integer and the matrix - prolog

I am quite new in prolog and I've met this structure and I could not figure out how to substact the integer (1) and the matrix.
The exact structure is:
s(1,
[
[[a], [b, c], [f], [s]],
[[4], [k], [1], [5]],
[[f], [s], [w], []],
[[4], [], [w], [3, 53]]
]
)
I've tried with functions that extract elements of lists/matrices, but I haven't met anything in () before.

My guess is you have a variable with the content s(Integer, Matrix) and want to extract the Integer and Matrix. This is actually quite easy:
Lets go with a dummy object S = s(3, [[[1,2],[a,b]]]). You only have S and want to access 3 and [[[1,2],[a,b]]]
?- S = s(3, [[[1,2],[a,b]]]),
S = s(I,M).
I = 3,
M = [[[1, 2], [a, b]]],
S = s(3, [[[1, 2], [a, b]]])
You can put this in some kind of function too. The following example will output an addtion if the predicate name is a, a substraction for s and or h it will put the first parameter as head of a list of the second parameter:
doIt(a(A,B),Out) :-
Out is A+B.
doIt(s(A,B),Out) :-
Out is A-B.
doIt(h(A,B),[A|B]).
?- doIt(a(2,1),A).
A = 3
?- doIt(s(2,1),A).
A = 1
?- doIt(h(2,1),A).
A = [2|1]

Related

How to create a infinite list if input is not delcared?

I have a written a functional function that tells the user if a list is ordered or not, given the list inputted. However, if a user inputs a variable as the input instead of a list, I would like to output an infinite list. How can I go about this? Here is the current code
ordered([]).
ordered([_]).
ordered([X,Y|Ys]) :- X =< Y , ordered( [Y|Ys] ).
Here is some input
? ordered([1,2,3]).
true
? ordered([1,5,2]).
false
I also want for variables to creat infinite list like so
? ordered(L).
L = [];
L = [_1322] ;
L = [_1322, _1323] ;
L = [_1322, _1323, _1324] ;
L = [_1322, _1323, _1324, _1325].
The list should increase until the user exits as shown.
The list should increase until the user exits as shown.
Solution:
ordered([]).
ordered([_]).
ordered([X,Y|Ys]) :- X #=< Y , ordered( [Y|Ys] ).
EDIT:
SWI Prolog doc
The arithmetic expression X is less than or equal to Y. When reasoning over integers, replace (=<)/2 by #=</2 to obtain more general relations. See declarative integer arithmetic (section A.9.3).
What properties should the list of variables have? The currently accepted answer by Anton Danilov says that [3, 2, 1] is not an ordered list:
?- List = [A, B, C], List = [3, 2, 1], ordered(List).
false.
but it also says that [3, 2, 1] is an instance of an ordered list:
?- List = [A, B, C], ordered(List), List = [3, 2, 1].
List = [3, 2, 1],
A = 3,
B = 2,
C = 1 ;
false.
Viewed logically, this is a contradiction. Viewed procedurally, it is fine, but also the #=< relationship between the variables in the list is meaningless. The comparison of the unbound variables does not say anything about the relationship of the list elements if they are bound to values at some point.
You can use constraints to exclude future unordered bindings:
:- use_module(library(clpfd)).
ordered([]).
ordered([_]).
ordered([X, Y | Xs]) :-
X #=< Y,
ordered([Y | Xs]).
This way you cannot bind the variables in the list to incorrect numbers later on:
?- List = [A, B, C], List = [3, 2, 1], ordered(List).
false.
?- List = [A, B, C], ordered(List), List = [3, 2, 1].
false.
But later correct ordered bindings are still allowed:
?- List = [A, B, C], ordered(List), List = [1, 2, 3].
List = [1, 2, 3],
A = 1,
B = 2,
C = 3 ;
false.
This may not be the best solution, but I believe it can give you some idea of how to do what you need. In SWI-Prolog, the predicate freeze(+Var,:Goal) delays the execution of Goal until Var is bound.
ordered([]).
ordered([_]).
ordered([X,Y|R]) :-
freeze( X,
freeze( Y,
( X #=< Y,
ordered([Y|R]) ) ) ).
Here are some examples with finite lists:
?- ordered([1,2,3]).
true.
?- ordered([1,2,3,0]).
false.
?- ordered(L), L=[1,2,3].
L = [1, 2, 3] ;
false.
?- ordered(L), L=[1,2,3,0].
false.
For an infinite list, you will need to "take" its prefix:
take([]).
take([_|R]) :- take(R).
Here is an example with infinite list:
?- ordered(L), take(L).
L = [] ;
L = [_375396] ;
L = [_376366, _376372],
freeze(_376366, freeze(_376372, (_376366#=<_376372, ordered([])))) ;
L = [_377472, _377478, _377484],
freeze(_377472, freeze(_377478, (_377472#=<_377478, ordered([_377484])))) ;
L = [_378590, _378596, _378602, _378608],
freeze(_378590, freeze(_378596, (_378590#=<_378596, ordered([_378602, _378608])))) ;
L = [_379720, _379726, _379732, _379738, _379744],
freeze(_379720, freeze(_379726, (_379720#=<_379726, ordered([_379732, _379738, _379744]))))

printing pairs of a list in SWI-prolog

basically, I want to print pairs from one list like this
?- [1 2 3 4 5,R]
the output is
R = [1, 2]
R = [1, 3]
R = [1, 4]
R = [1, 5]
R = [2, 3]
R = [2, 4]
R = [2, 5]
R = [3, 4]
R = [3, 5]
R = [4, 5]
I used the code that creates subsets and modified it
sub(0,_,[]).
sub(N,[X|T],[X|R]):-N>0,N1 is N-1,sub(N1,T,R).
sub(N,[_|T],R):-N>0,sub(N,T,R).
and I would call
sub(2,[1,2,3,4,5],R)
but is there a way to do it without using a counter?
Prolog is about defining relations (in the form of rules) and to try to avoid thinking procedurally (steps of execution to achieve a result). You can solve this by breaking it down into simple rules for the pairs:
For a list with head H and tail T, a valid pair is [H,E] where E is a member of T.
For a list with head H and tail T, a valid pair is a pair taken from T.
If you think about these rules, they are (1) mutually exclusive (there isn't a solution that matches both rules), and (2) they are complete (they cover all of the valid solutions).
Writing these in Prolog, you get:
pair([H|T], [H,E]) :- member(E, T).
pair([_|T], P) :- pair(T, P).
This provides a relational solution which yields:
| ?- sub([a,b,c,d], S).
S = [a,b] ? ;
S = [a,c] ? ;
S = [a,d] ? ;
S = [b,c] ? ;
S = [b,d] ? ;
S = [c,d] ? ;
(1 ms) no
| ?-
And works in a more general case:
| ?- pair(L, P).
L = [A,B]
P = [A,B] ? ;
L = [A,B|_]
P = [A,B] ? ;
L = [A,_,B|_]
P = [A,B] ? ;
L = [A,_,_,B|_]
P = [A,B] ? ;
...
an easy way:
?- L = [1,2,3,4,5], forall((nth1(I,L,X), nth1(J,L,Y), I<J), writeln(I/J)).
1/2
1/3
1/4
1/5
2/3
2/4
2/5
3/4
3/5
4/5
L = [1, 2, 3, 4, 5].
Yes, there is, since you don't have to account for subsets of arbitrary length.
There are two steps you need to account for, and both have two variants.
Select the first element of the pair:
Use the head of the list
Discard the head and pick it out of the tail of the list
Select the second element of the pair:
Use the head of the list
Discard the head and pick it out of the tail of the list
% Use the head as the first element
pairs((H, P2), [H | T]) :- pairs((H, P2), T).
% If we have the first element, use the head as the second element
pairs((P1, H), [H | _]) :- nonvar(P1).
% Ignore the head and pick what we need out of the tail
pairs(P, [_ | T]) :- pairs(P, T).

Deep Reverse in PROLOG - Lists

Hey I'm trying to create a predicate for the generating of a deep reverse on nested Lists in PROLOG.
Currently I got this predicate
reverse(L,A) :- rev(L,[], A).
rev([],A,A).
rev([H|L],R,A) :- rev(L,[H|R],A).
The result looks like this:
reverse([1,2,3],A).
A = [3, 2, 1].
reverse([[0,1],2,3],A).
A = [3, 2, [0, 1]].
The problem is, that the inner List is not reversed. It should look like this:
reverse([[0,1],2,3],A).
A = [3, 2, [1, 0]].
reverse([1,2,[3,4,5,[6,7],8],[9,10],11,12],A).
A = [12,11,[10,9],[8,[7,6],5,4,3],2,1].
Thanks for any help.
The way you represent your data is called defaulty, because you need a default case when reasoning over it:
is it a list? &rightarrow; something holds
otherwise &rightarrow; something else holds.
Such a representation is a rich source of troubles. Consider for example my_reverse/2 from the other answer. The main problem with it is that it prematurely and incorrectly commits to one of the cases, although both cases are still possible:
?- my_reverse([X], Ls).
Ls = [X].
But this answer only holds for the case where X is not a list! This problem leads to the following strange behaviour of the predicate:
?- my_reverse([X], Ls), X = [1,2,3].
Ls = [[1, 2, 3]],
X = [1, 2, 3].
This mean that even though X is a list, its elements are not reversed!
You should always aim for cleaner representations to distinguish the cases that can arise.
For example, what would you say about the following way to represent your data:
list(Ls) represents the list Ls
n(N) represents the number N.
With such a representations, we can distinguish the cases symbolically. I leave this as the starting point for a more declarative solution.
To keep things as simple as possible, we could add a test if the current element being checked is a list or not. If it is indeed a list, then its elements should be reversed as well. So in code:
my_reverse(L,R) :- rev(L,[],R).
rev([],A,A).
rev([H|T],A,R) :-
( is_list(H) -> % If H is a list
rev(H,[],X), % then reverse H as well
rev(T,[X|A],R)
;
rev(T,[H|A],R)
).
Also, not that it really matters, just to try and avoid confusion, note how I used A and R for respectively Accumulator and Result. In your code they are currently swapped, which -for me personally- can be a bit confusing, especially when predicates become longer and more complex.
Anyway, let's look at the queries you provided:
?- my_reverse([[0,1],2,3],R).
R = [3, 2, [1, 0]].
?- my_reverse([1,2,[3,4,5,[6,7],8],[9,10],11,12],R).
R = [12, 11, [10, 9], [8, [7, 6], 5, 4, 3], 2, 1].
And some general queries:
?- my_reverse(L,R).
L = R, R = [] ;
L = R, R = [_G2437] ;
L = [_G2437, _G2443],
R = [_G2443, _G2437] ;
L = [_G2437, _G2443, _G2449],
R = [_G2449, _G2443, _G2437] ;
L = [_G2437, _G2443, _G2449, _G2455],
R = [_G2455, _G2449, _G2443, _G2437]
...
?- my_reverse([[X,Y]|T],R), member(a,T), length(X,2).
X = [_G2588, _G2591],
T = [a],
R = [a, [Y, [_G2588, _G2591]]]
;
X = [_G2594, _G2597],
T = [a, _G2588],
R = [_G2588, a, [Y, [_G2594, _G2597]]]
;
X = [_G2594, _G2597],
T = [_G2582, a],
R = [a, _G2582, [Y, [_G2594, _G2597]]]
...
Note however that using this predicate, no termination occurs after finding the first answer to the query:
?- my_reverse(X,[X]).
X = [X] ;
...
But since this wasn't a requirement/demand in OP's question, I assumed it to be okay.
EDIT:
Please read #mat's answer as a follow-up to this problem.
an additional solution for your problem is to use cut and the built-in predicate "is_list/1" to check if you treat a simple term or a list in the current call.
here is the code:
deepReverse(List,R):-deepReverseTail(List,[],R).
deepReverseTail([],Acc,Acc).
deepReverseTail([H|T],Acc,R):- % when H is a list
is_list(H), % check if it's a list.
!, % cut the process if not.
deepReverseTail(H,[],Hrev), % reverse this current list
deepReverseTail(T,[Hrev|Acc],R). % continue the general recursion
deepReverseTail([H|T],Acc,R):- deepReverseTail(T,[H|Acc],R). % when H is a simple term
the "cut" in the third line make sure you treat only list in this definition, while treating simple terms will be in the next definitions.
an output example:
7 ?- deepReverse([a,[d,f],[],[[k],g]],R)
R = [[g, [k]], [], [f, d], a].

How to generate every [X,Y] possible for a given list?

I'm trying to generate every combination possible given a list. I want every [X,Y] combination possible.
Here's an example :
?- arguments(A,[1,2,3]).
A = [1,2] ; A = [1,3] ; A = [2,1] ; A = [2,3] ; A = [3,1] ;
A = [3,2]
I have tried multiple things, but I've yet to find a working one.
I am pretty sure the idea is to use prolog's ability to try every possibility as such :
element(X,[X|_],1).
element(X,[_|Q],N) :- element(X,Q,NewN), N is NewN + 1.
This predicate can return the element at the position N, or return the position of the element X, or generate every possibility. Exemple :
?- element(X,[a,b,c],N).
N = 1
X = a
N = 2
X = b
N = 3
X = c
Thanks for the help.
Edit following gusbro answer :
I can't use already existing predicates, it's part of a course.
Reading your answer, I came up with this :
remove_element_x(X, [X|Q], Q).
remove_element_x(X, [T|Q], [T|Res]) :- remove_element_x(X,Q,Res).
arguments([X,Y],L) :-
element(X,L,_),
remove_element_x(X,L,L2),
element(Y,L2,_).
remove_element_x/3 remove the element x from the list and returns the new list.
But the backtracking is not working :
?- arguments(A,[1,2,3]).
A = [1,2] ?
yes
You can use select/3 to select an element from a list (and get the remaining list), then do it again to select another element from the remaining list).
i.e.:
arguments([A,B], L):-
select(A, L, L1),
select(B, L1,_).
Test case:
?- arguments(A,[1,2,3]).
A = [1, 2] ;
A = [1, 3] ;
A = [2, 1] ;
A = [2, 3] ;
A = [3, 1] ;
A = [3, 2]

Create a newlist with elements of the sublists by my List

I have this list :
C = [[1,0],[2,3],[1,2],[1,3]]
I'll like find if the number 1 included in a sublist inside my list in position [1,_ ] and i like to save to a list Newlist the number of X ..... [1,X].
I will give an example... i have the list C and i am searching for sublist which first element it's 1 and give me the Newlist.
The Newlist must be : Newlist=[0,2,3]
It had the second element of the sublists who has the number 1 at the first element.
If you use SWI-Prolog with module lambda.pl, (you can find it at http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl) you can write
:- use_module(library(lambda)).
my_filter(V, L, R) :-
foldl(V+\X^Y^Z^(X = [V,W]
-> append(Y, [W], Z)
; Z = Y),
L, [], R).
nth0/3 allows to access list' elements by index:
?- C = [[1,0],[2,3],[1,2],[1,3]], findall(P, nth0(P, C, [1,_]), NewList).
C = [[1, 0], [2, 3], [1, 2], [1, 3]],
NewList = [0, 2, 3].
edit I'm sorry I didn't read the question right. nth0 is misleading. Could be instead
findall(E, member([1,E], C), NewList)
You need a "filter". This is what it could look like:
filter_1_at_pos_1([], []). % The new list is empty when the input list is empty
filter_1_at_pos_1([[1,X]|Sublist], [X|Xs]) :- % The first element is 1 so the
% second element belongs to the
% new list
!, filter_1_at_pos_1(Sublist, Xs). % filter the remainder of the list
filter_1_at_pos_1([[N,_]|Sublist], Xs) :-
N \== 1, % The first element is not 1, ignore the second element
!, filter_1_at_pos_1(Sublist, Xs).
As #mbratch suggested, just define the solution for one element of the input list for each possible condition, in this case 1) empty list 2) first element is 1 and 3) first element is not 1.
?- C = [[1,0],[2,3],[1,2],[1,3]], filter_1_at_pos_1(C, NewList).
C = [[1, 0], [2, 3], [1, 2], [1, 3]],
NewList = [0, 2, 3].
The cuts make the predicate deterministic. The cut in the last clause is not necessary.

Resources