Tuple to list in Prolog - list

Recently I'm doing a program and it requires me to convert a tuple to a list.
Tuples look like this: [(1,[1,2,3,4]), (1,[2,3,4,5]), ...]
And what I want is a list of: [(1,2,3,4), (2,3,4,5), ...]
Is there any way I can do that?

In Prolog, (1, 4, 2, 5), is syntactical sugar for (1, (4, (2, 5))), just like [1, 4, 2, 5] is syntactical sugar for [1|[4|[2|[5|[]]]]] (note however that the list ends with an empty list [], whereas for a tuple, it ends with a (2, 5)).
list_tuple([A, B], (A, B)).
list_tuple([A|T], (A, B)) :-
list_tuple(T, B).
So then we can write a predicate to unpack the list out of the 2-tuple, and convert the list to a tuple:
conv((_, L), R) :-
list_tuple(L, R).
and we can use maplist/3 to perform the conversion over the entire list:
convlist(As, Bs) :-
maplist(conv, As, Bs).
This then yields:
?- convlist([(1,[1,2,3,4]), (1,[2,3,4,5])], R).
R = [(1, 2, 3, 4), (2, 3, 4, 5)] ;
false.
Tuples are however in Prolog not very common, so I do not see why you do not stick with the list itself.

Related

How to write the result in list instead of printing out in prolog

I'm writing a predicate for finding the bigger number in pairs. If the number has no pair - it will be just added.
write_list([A|[]]):- write(A).
write_list([A, B|Tail]) :- ((A>B, write(A));(A<B,write(B))), nl,
write_list([B|Tail]).
My problem is, I cannot figure out how to write a result in another list instead of printing the result out:
write_list([1,2,6,8,5], X).
X = [2,6,8,8,5].
write only prints the content to the standard output, it does not "yield" it to the result list. In Prolog the only way to generate values, is through unification.
You thus need to define a predicate maxpair/2, not write_list/1.
The predicate thus looks like:
:- use_module(library(clpfd)).
maxpair([A], [A]).
maxpair([A, B|Tail], [H|T]) :-
H #= max(A, B),
maxpair([B|Tail], T).
The first clause says that the maxpair/2 of a singleton list is that singleton list. The latter says that the maxpair/2 for a list containing two or more lists is a list that starts with the maximum of the first two elements, and we recurse on the tail of the list.
The above can also yield a list in reverse. For example:
?- write_list(L, [5, 3, 2, 1]).
L = [5, 3, 2, 1] ;
false.
?- write_list(L, [1, 4, 2, 5]).
false.
?- write_list(L, [3, 3, 5, 5]).
L = [_542, _548, _554, 5],
_542 in inf..3,
3#=max(_542, _548),
_548 in inf..3,
3#=max(_548, _554),
_554 in inf..3 ;
false.
?- write_list(L, [3, 5, 5, 4]).
L = [_1128, _1134, 5, 4],
_1128 in inf..3,
3#=max(_1128, _1134),
_1134 in inf..3 ;
false.
So depending on the situation it can:
fully reconstruct the list;
construct a list with some variables with intervals; or
proof that it is impossible to construct such a list.

Why is this row in prolog returning false?

I am trying to write a Prolog code, but I can't get this to return true. I am trying to find a list, which all elements are included in two other lists. For example all list A elements are found in B and C lists each, not together.
My Prolog code is :
member(X, [X|_]).
member(X, [_|T]) :-
member(X, T).
first([H0|T0], [H0|T1], A) :-
member(H0, A),
first(T0, [H0|T1], A).
first([H0|T0], [_|T1], A) :-
first([H0|T0], T1, A).
where member predicate returns true if an element is in a list. With predicate 'first' I am trying to use member predicate to find a matching element of A and B in C list. If I find, then go further in the first list and compare its first element to second lists elements and again, if I would matching, I check with if I can find it in third list. I hope it does this, but when I run
?- first([4, 6, 4], [4, 5, 6, 4], [1, 2, 4, 6]).
it gives false and I can't figure out why. This seems as a simple attention mistake somewhere, but I just can't get my head around it.
I don't know anything about prolog, but like everyone I've been bitten by logic errors before. (=
As I have commented, you seem to lack a base case for first([], _, _). An example:
first([4], [4], [4]) :-
member(4, [4]), // quite true
first([], [4], [4]). // No matching rule, as all those assume an existing head in the first argument
I am not sure I understood your question, but allow me to try to specify further your predicate first/3:
first(+L, +L1, +L2)
succeeds if every element of L is found either in L1 or in L2.
If this is what you're looking for, then:
first([], _, _).
first([E|L], L1, L2) :-
(member(E, L1); member(E, L2)),
first(L, L1, L2).
Examples of success:
first([1, 2, 3], [1, 2, 3], [1, 2]).
first([1], [1, 2, 3], [1, 2]).
first([1, 2, 3], [1, 2, 3], []).
Examples of faiure:
first([1, 2, 3, 5], [1, 2, 3], [1, 2]).
first([7], [1, 2, 3], [1, 2]).
first([1, 2, 3], [], []).

Ungrouping a (key, list(values)) pair in Spark/Scala

I have data formatted in the following way:
DataRDD = [(String, List[String])]
The first string indicates the key and the list houses the values. Note that the number of values is different for each key (but is never zero). I am looking to map the RDD in such a way that there will be a key, value pair for each element in the list. To clarify this, imagine the whole RDD as the following list:
DataRDD = [(1, [a, b, c]),
(2, [d, e]),
(3, [a, e, f])]
Then I would like the result to be:
DataKV = [(1, a),
(1, b),
(1, c),
(2, d),
(2, e),
(3, a),
(3, e),
(3, f)]
Consequently, I would like to return all combinations of keys which have identical values. This may be returned into a list for each key, even when there are no identical values:
DataID = [(1, [3]),
(2, [3]),
(3, [1, 2])]
Since I'm fairly new to Spark and Scala I have yet to fully grasp their concepts, as such I hope any of you can help me. Even if it's just a part of this.
This is definitely a newbie question that often times comes up. The solution is to use flatMapValues
val DataRDD = sc.parallelize(Array((1, Array("a", "b", "c")), (2, Array("d", "e")),(3, Array("a", "e", "f"))))
DataRDD.flatMapValues(x => x).collect
Which will give the desired solution
Array((1,a), (1,b), (1,c), (2,d), (2,e), (3,a), (3,e), (3,f))

Taking a tree and making a list

I have written a program that can take a list and change it into a tree.
build_tree([X,Y],'Tree'(X,Y)) :- !.
build_tree([X|Y],'Tree'(X,Z)) :- build_tree(Y, Z).
If I want to reverse the process and take the tree and change it back into a list, how would I do this?
Note that your tree->list conversion isn't a function since trees may correspond to multiple lists:
?- build_tree([1, 2, 3], T).
T = 'Tree'(1, 'Tree'(2, 3)).
?- build_tree([1, 'Tree'(2, 3)], T).
T = 'Tree'(1, 'Tree'(2, 3)).
If you want a predicate that can generate all lists from a tree, remove the cut from build_tree and apply it with a variable first argument. If you want a deterministic conversion, write a new predicate tree_to_list.
Just curious, how would that deterministic version play out? Assuming there was only one possible list, from the tree, for example:
('Tree'('Tree'(nil, 2, nil), 5, 'Tree'(nil, 6, nil)).
Which gives: L = [5, 2, 6]
If you remove the cut from the first rule, your code it's ready to work in 'backward' mode:
?- build_tree([1,2,3,4],T).
T = 'Tree'(1, 'Tree'(2, 'Tree'(3, 4))) ;
false.
?- build_tree(X,$T).
X = [1, 'Tree'(2, 'Tree'(3, 4))] ;
X = [1, 2, 'Tree'(3, 4)] ;
X = [1, 2, 3, 4] ;
false.
flatten(leaf, []).
flatten(node(L, E, R), Ls) :-
flatten(L, Ls1),
append(Ls1, [E], Ls2),
flatten(R, Ls3),
append(Ls2, Ls3, Ls).
if you consider tree ass node(leaf,Element,leaf) for example
flatten(node(node(leaf,2,leaf),3,node(leaf,5,leaf)),X).
gives X=[2,3,5].
and if you wanna have bst
List to Tree.
insert(E,leaf,node(leaf,E,leaf)).
insert(E,node(L,N,R),T) :-
E >= N,
T=node(L,N,R1),
insert(E,R,R1).
insert(E,node(L,N,R),T) :-
E < N,
T=node(L1,N,R),
insert(E,L,L1).
list_to_tree(List,Tree) :-
list_to_tree(List,leaf,Trea2),
Tree=Trea2.
list_to_tree([],Tree,Tree).
list_to_tree([H|T],Tree,St):-
insert(H,Tree,R),
list_to_tree(T,R,St).

GNU Prolog - Loop and new list

This is just kind of general question, steming from something else.
Say you want the product table from a matrix ( I think thats what its called).
Example i put in
outer([1,2,3],[4,5,6],L).
Then L = [[4,5,6],[8,10,12],[12,14,18]]
So i want to iterate through two lists and create a new list.
I got this:
outer(L1,L2,L3) :-
append(LL,[L|RL],L1),
append(LE,[E|RE],L2),
Prod is L * E, !,
append(LE,[Prod|RE], NewL),
append(LL,[NewL|RL], L3).
which is kind of close. I know i can use append to iterate through both Lists, not sure how to create a new list. Always have trouble when it comes to creating a completely new list.
Thanks.
product([],_,[]).
product([H1|T1],L2,R):- mul(H1,L2,R1),product(T1,L2,R2),append([R1],R2,R).
mul(X,[],[]).
mul(X,[H|T],[Z|R]):-Z is X*H, mul(X,T,R).
Here's another, it uses map instead of append. Dot-products are produced for products involving a non number. It's also deterministic.
The multiplier:
amul([], _Other_Row,[]).
amul([X|Xs],Other_Row,[Row_Out|Rest_Out]) :-
maplist(mul(X),Other_Row, Row_Out),
amul(Xs,Other_Row, Rest_Out).
The product predicate:
mul(X,Y, Prod) :-
( number(X), number(Y)
-> Prod is X * Y
; true
-> Prod = dot(X,Y)
).
[1,3,5] X [2,4,6]
?- amul([1,3,5], [2,4,6],Prod).
Prod = [[2, 4, 6], [6, 12, 18], [10, 20, 30]].
[a,b,c] X [1,2,3,4]
?- amul([a,b,c],[1,2,3,4],Prod).
Prod = [[dot(a, 1), dot(a, 2), dot(a, 3), dot(a, 4)],
[dot(b, 1), dot(b, 2), dot(b, 3), dot(b, 4)],
[dot(c, 1), dot(c, 2), dot(c, 3), dot(c, 4)]].