Prolog: Filter and list - list

Construct a predicate called fPairsAtoms/3 so that given an atom (first argument), and a list of pairs, unify a third parameter with the filtered list of pairs by selecting only the pairs that have the first component as the atom of the first argument.
Example:
fPairsAtoms(sA,[[basA,absAb],[ab,bbsA],[sA,abbsB],[bsA,sAsB],[sA,bb]],X)
Result:
X = [[sA,abbsB],[sA,bb]]
I do not understand ..... What should I face these types of exercises?
Can you help me find a solution?
Today I started with prolog, I am a newbie in every way.

If you've just started today, it probably is a bit too soon for you to tackle this problem.
First you should understand what Prolog terms are: atoms, logical Variables, compound terms foo(x,X,bar(baz)).
Then you should understand unification, a = a, a = A, A = a, A = foo(a), foo(A) = foo(a), [atom, B] = [A, bar].
You should understand lists representation, where
[ A, B, C ]
= [A, B | [C] ]
= [A | [B , C ]]
= [A | [B | [C] ]]
= ....
= [A , B , C | []]
so that unifying [A | B] = [a] succeeds, resulting in also unifying A = a and B = [], but unifying [A | B] = [] fails.
Then you need to understand predicates, which under procedural interpretation mean,
to_prove(This) :- need_to_prove(This) , and_also(That).
So that
fPairsAtoms(sA, [[basA,absAb],[ab,bbsA],[sA,abbsB],[bsA,sAsB],[sA,bb]], X) :-
X = [ [sA,abbsB], [sA,bb]].
is a perfectly valid, though exceedingly narrow, definition of one.
But then so are also
fPairsAtoms(sA, [[basA,absAb],[ab,bbsA],[sA,abbsB] | [[bsA,sAsB],[sA,bb]] ], X) :-
X = [ [sA,abbsB] | [ [sA,bb]] ].
% and
fPairsAtoms(sA, [ [ab,bbsA],[sA,abbsB] | [[bsA,sAsB],[sA,bb]] ], X) :-
X = [ [sA,abbsB] | [ [sA,bb]] ].
% and
fPairsAtoms(sA, [ [sA,abbsB] | [[bsA,sAsB],[sA,bb]] ], X) :-
X = [ [sA,abbsB] | [ [sA,bb]] ].
% and
fPairsAtoms(sA, [[bsA,sAsB],[sA,bb]] , Y) :-
Y = [ [sA,bb]].
% ... and
fPairsAtoms(sA, [] , Y) :-
Y = [].
and so also
fPairsAtoms(sA, [ [sA,abbsB] | L ], X) :-
L = [[bsA,sAsB],[sA,bb]],
Y = [ [sA,bb]],
X = [ [sA,abbsB] | Y ].
and thus
fPairsAtoms(sA, [ [sA,abbsB] | L ], X) :-
L = [[bsA,sAsB],[sA,bb]],
fPairsAtoms( L, Y),
Y = [ [sA,bb]],
X = [ [sA,abbsB] | Y ].
% and
fPairsAtoms(sA, [ [sA,abbsB] | L ], X) :-
L = [[bsA,sAsB],[sA,bb]],
fPairsAtoms( L, Y),
X = [ [sA,abbsB] | Y ].
% and
fPairsAtoms(sA, [ [sA,abbsB] | L ], X) :-
fPairsAtoms( L, Y),
X = [ [sA,abbsB] | Y ].
% and so
fPairsAtoms(sA, [ A | L ], X) :-
A = [sA, B ],
fPairsAtoms( L, Y),
X = [ A | Y ].
% and even
fPairsAtoms(SA, [ A | L ], X) :-
A = [SA, B ],
fPairsAtoms( SA, L, Y),
X = [ A | Y ].
But on the other hand, in cases were there was no match, we saw that it is
fPairsAtoms(SA, [ A | L ], X) :-
A = [SB, B ],
dif( SA, SB),
fPairsAtoms( SA, L, Y),
X = Y .
% i.e.
fPairsAtoms(SA, [ [SB, B ] | L ], X) :-
dif( SA, SB),
fPairsAtoms( SA, L, X) .
So which one of the two clauses, that we've ended up with,
fPairsAtoms( SA, [ [SA, _] | L ], X) :-
fPairsAtoms( SA, L, Y),
X = [A | Y].
fPairsAtoms( SA, [ [SB, _] | L ], X) :-
dif( SA, SB),
fPairsAtoms( SA, L, X).
is the right one? The answer is: both!

To filter the pairs in the list, you need to traverse it while comparing the given atom with the first element of each pair. A trivial predicate to traverse a list would be:
traverse([]).
traverse([Head| Tail]) :-
traverse(Tail).
The predicate in your problem description is terribly named and don't follow recommended Prolog coding guidelines. Let's rename it to filter_pairs_by_key/3 and change the argument order to filter_pairs_by_key(Pairs, SearchKey, FilteredPairs). Also, the recommended representation for a pair in Prolog is Key-Value. There are standard predicates and library predicates that expect this representation (e.g. keysort/2). Based on the traverse/2 predicate template and the code style recommendations, we can write:
filter_pairs_by_key([], _, []).
filter_pairs_by_key([Key-Value| Pairs], SearchKey, [Key-Value| FilteredPairs]) :-
Key = SearchKey,
filter_pairs_by_key(Pairs, Atom, FilteredPairs).
filter_pairs_by_key([Key-_| Pairs], SearchKey, FilteredPairs) :-
Key \= SearchKey,
filter_pairs_by_key(Pairs, SearchKey, FilteredPairs).
Note that I'm using two clauses for the non-empty list case: one when the pair key matches the atom and one when the match fails.
Sample call:
| ?- filter_pairs_by_key([basA-absAb,ab-bbsA,sA-abbsB,bsA-sAsB,sA-bb], sA, FilteredPairs).
FilteredPairs = [sA-abbsB,sA-bb] ?
yes
More can be said about this problem and this particular solution but, as mentioned in the comments, this is not a beginners exercise. Consider the comments recommendations and after being comfortable with Prolog list notation play with this solution.

Related

Haskell Nested List Comprehensions

I am studying for an exam and I am looking at an example of nested list comprehensions from the book "Learn you a Haskell", and I was hoping if anyone could explain me step by step how to analyze it and come out with its output.
let xxs = [[1,2,3],[2,3,4],[4,5]]
[ [ x | x <- xs, even x] | xs <- xxs ]]
Output: ([[2],[2,4],[4]])
[ [ x | x <- xs, even x] | xs <- xxs ]
[ [ x | x <- xs, even x] | xs <- [[1,2,3],[2,3,4],[4,5]] ]
[ [ x | x <- [1,2,3], even x] , [ x | x <- [2,3,4], even x] , [ x | x <- [4,5], even x] ]
[filter even [1,2,3], filter even [2,3,4], filter even [4,5]]
[[2],[2,4],[4]]
Or
[ [ x | x <- xs, even x] | xs <- xxs ]
map (\xs -> [ x | x <- xs, even x] ) xxs
map (\xs -> filter even xs) [[1,2,3],[2,3,4],[4,5]]
[filter even [1,2,3], filter even [2,3,4], filter even [4,5]]
[[2],[2,4],[4]]
Note this isn't the transformation that GHC actually does, just a way of writing it that might help you understand the output.
List comprehensions could have been defined by few identities:
[ f x | x <- [], ... ] === []
[ f x | x <- [y], ... ] === [ f y | {y/x}... ] -- well, actually, it's
-- case y of x -> [ f y | {y/x}... ] ; _ -> []
[ f x | x <- xs ++ ys, ...] === [ f x | x <- xs, ...] ++ [ f x | x <- ys, ...]
[ f x | True, ...] === [ f x | ... ]
[ f x | False, ...] === []
The handling of complex patterns (as opposed to simple variable patterns) is elided, only hinted at, for simplicity. {y/x}... means, y is substituted for x in .... For actual definition, see the Report.
It follows that
[ f x | xs <- xss, x <- xs] === concat [ [f x | x <- xs] | xs <- xss]
and
[ f x | x <- xs, test x ] === map f (filter test xs)
Your expression is equivalent to
[ [ x | x <- xs, even x] | xs <- xxs ] -- `]`, sic!
=
[ f xs | xs <- xxs ] where f xs = [ x | x <- xs, even x]
Which is to say, there's nothing special about a list comprehension being used as a value expression in the definition of f. It looks "nested", but actually, it isn't.
What is nested, are the generator expressions separated by commas:
[ x | xs <- xss, x <- xs ] === concat [ [x | x <- xs] | xs <- xss ]
-- ^^^ nested generator
(the equivalency like we saw above.) So then,
[ [ x | x <- xs, even x] | xs <- [[1,2,3],[2,3,4],[4,5]] ]
=
[ [ x | x <- [1,2,3], even x]] ++ [[ x | x <- [2,3,4], even x]] ++ [[ x | x <- [4,5], even x] ]
=
[ [ x | x <- [1,2,3], even x], [ x | x <- [2,3,4], even x], [ x | x <- [4,5], even x] ]
=
[ [ x | x <- [1], even x]++[ x | x <- [2], even x]++[ x | x <- [3], even x]
, [ x | x <- [2], even x]++[ x | x <- [3], even x]++[ x | x <- [4], even x]
, [ x | x <- [4], even x]++[ x | x <- [5], even x] ]
=
[ [ 1 | even 1]++[ 2 | even 2]++[ 3 | even 3]
, [ 2 | even 2]++[ 3 | even 3]++[ 4 | even 4]
, [ 4 | even 4]++[ 5 | even 5] ]
=
[ []++[ 2 ]++[], [ 2 ]++[]++[ 4 ], [ 4 ]++[] ]
=
[ [2], [2,4], [4] ]
Or, with filter if you'd prefer,
[ [ x | x <- [1,2,3], even x], [ x | x <- [2,3,4], even x], [ x | x <- [4,5], even x] ]
=
[ filter even [1,2,3], filter even [2,3,4], filter even [4,5] ]
=
[ [2], [2,4], [4] ]

Prolog - unifying two lists with/without variables

This Prolog code returns:
?- [a,b,c,d] = [a|[b,c,d]].
true
and this one
?- [X,Y] = [a|[b,c,d]].
returns false.
I am not totally grasping why [X, Y] is false. Trace is not helpful here. I would expect the following assignment to hold
X = a
Y = [b,c,d]
and the statement be true.
What does | do besides splitting on head and tail?
A list in Prolog is implemented as a linked list of functors. If you write a list like [a, b, c, d]. it looks in reality like:
+-------+
| (|)/2 |
+---+---+ +-------+
| o | o---->| (|)/2 |
+-|-+---+ +---+---+ +-------+
v | o | o---->| (|)/2 |
a +-|-+---+ +---+---+ +-------+
v | o | o---->| (|)/2 |
b +-|-+---+ +---+---+
v | o | o----> []
c +-|-+---+
v
d
or in Prolog notation [a | [b | c | [d | [] ] ] ]. The comma-separated list is syntactical sugar: if you write [a, b, c, d], the Prolog interpreter converts it to a representation as above.
Since [b, c, d] is equal to:
[ b | [ c | [ d | [] ] ] ]
and thus [ a | [b, c, d] ] is thus equal to
[a | [b | c | [d | [] ] ] ]
But the list [X, Y] is just equal to
[X, Y] == [ X | [ Y | [] ] ]
or in a structural way:
+-------+
| (|)/2 |
+---+---+ +-------+
| o | o---->| (|)/2 |
+-|-+---+ +---+---+
v | o | o----> []
X +-|-+---+
v
Y
If we then match it with [a | [b | c | [d | [] ] ] ] this means the "outer" shell can be matched, so X = a, but then Y = b, and [] = [ c | [ d | [] ] ]. The last part does not match, and thus it returns false. The X and Y are thus not the problem. The problem is that [] is a constant, and it does not match with the functor that represents [ c | [d] ].
If we would for example unify [ X | Y ] == [a, b, c, d] we get:
?- [ X | Y ] = [a, b, c, d].
X = a,
Y = [b, c, d].
So to conclude, one can say that | itself "does" nothing. It is a functor, just like f(1, 2). In Lisp they used cons [wiki] for this, and nil for the empty list. So [1, 4, 2, 5] looks in Lisp like cons 1 (cons 4 (cons 2 (cons 5 nil))), or in Prolog it would look like cons(1, cons(4, cons(2, cons(5, nil)))). It is only a bit cumbersome to write. In fact the comma separated notation is more the "magic" part. Prolog just performs unification for lists, just like it does for other functors and constants.

I need to combine all elements in a list using only prelude and no other modules in Haskell

n is the first argument, and a list is the second. The elements can be can selected several times and in different order.
So it will look something like:
com 1 [1,2,3] = [ [1], [2], [3] ]
com 2 [1,2,3] = [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]]
Ive written these and they work but i need a general function
com :: Int -> [t] -> [[t]]
com x [] = []
com 1 ys = [[z]| z <- ys]
com 2 ys = [z:q:[] | z <- ys, q <- ys]
I think it will look something like this:
com x ys
| x < 0 = []
| otherwise qs = [ z:[] | z <- ys ] com (x-1) qs
all help appreciated
You started good:
com :: Int -> [t] -> [[t]]
com x [] = {- [] -} [[]] -- thanks to #cirdec for spotting this
com 1 ys = [ [z] | z <- ys]
com 2 ys = [ [z,q] | z <- ys, q <- ys] -- <<----
now continue with it for a while:
com 3 ys = [ [y,z,q] | y <- ys, z <- ys, q <- ys]
= [ y:[z,q] | y <- ys, z <- ys, q <- ys]
= [ y:[z,q] | y <- ys, [z,q] <- [ [z,q] | z <- ys, q <- ys]] -- <<----
= [ y:r2 | y <- ys, r2 <- [ [z,q] | z <- ys, q <- ys]] -- <<----
= [ y:r2 | y <- ys, r2 <- ...... ]
right? We can always replace equals by equals, in Haskell!
com 4 ys = [ [x,y,z,q] | x <- ys, y <- ys, z <- ys, q <- ys]
= [ x:[y,z,q] | x <- ys, y <- ys, z <- ys, q <- ys]
= ....
= [ x:r3 | x <- ys, r3 <- ...... ]
can you continue this? can you finish up this line of thought?
com n ys | n > 4 = [ x:r | x <- ys, r <- .... (n-1) .... ]

Prolog recursing endlessly in getList predicate

This predicate is intended to tell if the list has the element in it and add it to a new list. However, once I finish recursing through and I have the correct list being returned, it recurses backwards until it ends up at the beginning again and then recurses through it again -- endlessly.
getList([],X,[]).
getList([H|T],Side,Others) :-
(length(T,3)),
(H == Side),
append([],[H],NewList),
getList(T,Side,NewList).
getList([H|T],Side,Others) :-
(H == Side),
append(Others, [Side], Others1),
getList(T,Side,Others1). // where it backwards recurses after finishing
getList([E],X,[]).
Please help me determine WHY it does this as well as find a solution.
If I understood your description of the predicate right it searches in the first list for the element(s) identical to the Element and copies the Element in the second list.
This predicate can be implemented as follows:
getList( Element, OldList, NewList ).
getList( Element, [], [] ).
getList( Element, [ X | Xs ], [ Element | Ys ]) :-
X == Element,
getList( Element, Xs, Ys ).
getList( Element, [ X | Xs ], Ys ) :-
% X \== Element,
getList( Element, Xs, Ys ).
The following query is succeded with the result NewList
?- getList( a(X), [ a(1), a(a), a(Y), a(X), b(Y), a(X) ], NewList ).
yes
NewList = [ a(X), a(X) ].
P.S. length( X, 3 ) will give you [ _ , _ , _ ] if X is an unbound variable.

filter list into separate lists

I need to filter the list [#,d,e,#,f,g] such that I get the output as [[d,e],[f,g]] ,
I am stuck while creating a new list every time I encounter '#' is there a way to do this?
I tried the code below,
filterL([],List) :-[].
filterL([Head|Tail],X) :-
( Head \='#'->
append(X,Head,List),
filterL(Tail,List)
; filterL(Tail,X)
).
Your problem is not very well defined. Are empty sequences allowed or not? Shall [#] be related to [[],[]] (there is an empty sequence before and after) or []? You say it should be []. So:
list_splitbyhash(Xs, Xss) :-
phrase(splitby(Xss,#), Xs).
splitby([],_E) -->
[].
splitby(Xss,E) -->
[E],
splitby(Xss,E).
splitby([Xs|Xss],E) -->
{Xs = [_|_]},
all_seq(dif(E),Xs),
splitby(Xss,E).
all_seq(_, []) --> [].
all_seq(C_1, [C|Cs]) -->
[C],
{call(C_1,C)},
all_seq(C_1, Cs).
Here is another version, which uses an even more general approach:
list_splitbyhash(Xs, Xss) :-
phrase(by_split(=(#), Xss), Xs).
=(X,X,true).
=(X,Y,false) :- dif(X,Y).
by_split(_C_2, []) --> [].
by_split(C_2, Xss) -->
[E],
{call(C_2,E,T)},
( { T = true },
by_split(C_2, Xss)
| { T = false, Xss = [[E|Xs]|Xss1] },
all_seq(callfalse(C_2),Xs),
el_or_nothing(C_2),
by_split(C_2, Xss1)
).
callfalse(C_2,E) :-
call(C_2,E,false).
el_or_nothing(_) -->
call(nil).
el_or_nothing(C_2), [E] -->
[E],
{call(C_2,E,true)}.
nil([], []).
With lambdas, this can be expressed more compactly. Instead of
all_seq(callfalse(C_2),Xs)
and the definition for callfalse/3, one can now write
all_seq(C_2+\F^call(C_2,F,false))
With meta-predicate splitlistIf/3 and the reified equality predicate (=)/3, the task at hand becomes a one-liner---that is both efficient and logically pure!
?- splitlistIf(=(#),[#,d,e,#,f,g],Xs).
Xs = [[d,e],[f,g]]. % succeeds deterministically
As the code is monotone, logical soundness is ensured even for quite general queries:
?- Xs = [A,B,C], splitlistIf(=(X),Xs,Yss).
Xs = [A,B,C], X=A , X=B , X=C , Yss = [ ] ;
Xs = [A,B,C], X=A , X=B , dif(X,C), Yss = [ [C]] ;
Xs = [A,B,C], X=A , dif(X,B), X=C , Yss = [ [B] ] ;
Xs = [A,B,C], X=A , dif(X,B), dif(X,C), Yss = [ [B,C]] ;
Xs = [A,B,C], dif(X,A), X=B , X=C , Yss = [[A] ] ;
Xs = [A,B,C], dif(X,A), X=B , dif(X,C), Yss = [[A],[C]] ;
Xs = [A,B,C], dif(X,A), dif(X,B), X=C , Yss = [[A,B] ] ;
Xs = [A,B,C], dif(X,A), dif(X,B), dif(X,C), Yss = [[A,B,C]].