mirroring a list in prolog - list

My wanted output is this:
?- mirror ([1,2], [] , X ).
X= [1,2,2,1]
What I have so far:
mirror(L,R,X):- L is R , [R| revertList(L,X)] .
I cant think of how this works, please help me

It is not very different from reversing a list, but how you write it is not going to work. I googled "Prolog is" and after maybe 10 seconds I see that is/2 is for arithmetic expressions. I also don't know how you think that you can put predicate but maybe it is not possible? If you want to just append then you can use append to append the mirror reversed list to the end of the original list to get the final "mirror" result:
mirror(X, Y) :- reverse(X, R), append(X, R, Y).
but this is too easy? So I wonder maybe there is more to this question? I don't know why you have three arguments when you only need two arguments? Maybe you thought that you can use an accumulator to reverse the list because to reverse a list you use accumulator like this?
list_rev(L, R) :- list_rev(L, [], R).
list_rev([], R, R).
list_rev([X|Xs], Ys, R) :-
list_rev(Xs, [X|Ys], R).
But this is very easy to google, I just googled it and found it, so maybe you googled it too and you didn't like it? To get "mirrored" you just need to keep the original list too, like so:
list_mirrored(L, M) :- list_mirrored(L, [], M).
list_mirrored([], M, M).
list_mirrored([X|Xs], Ys, [X|Zs]) :-
list_mirrored(Xs, [X|Ys], Zs).
I wasn't sure if this is correct and I googled "Prolog append" and this is how it is done.

To describe lists in Prolog, always also consider DCG notation.
For example, in this concrete case:
mirror([]) --> [].
mirror([M|Ms]) --> [M], mirror(Ms), [M].
Your test case:
?- phrase(mirror([1,2]), Ls).
Ls = [1, 2, 2, 1].
It also works in the other direction. For example:
?- phrase(mirror(Ls), [a,b,c,c,b,a]).
Ls = [a, b, c] ;
false.
The most general query yields:
?- phrase(mirror(Ls), Ms).
Ls = Ms, Ms = [] ;
Ls = [_5988],
Ms = [_5988, _5988] ;
Ls = [_5988, _6000],
Ms = [_5988, _6000, _6000, _5988] ;
Ls = [_5988, _6000, _6012],
Ms = [_5988, _6000, _6012, _6012, _6000, _5988] ;
etc.
See dcg for more information.
Note that with the definition above, we have:
?- phrase(mirror(Ls), [a,b,a]).
false.
I leave generalizing this definition (if necessary) as an easy exercise.

This would get you the desired "output":
mirror(_,_,[1,2,2,1]).
That probably won't work for most inputs, but since you haven't explained the relationship between input and output for anything but this one case, that's a good as I can do.

Related

How can I test a non-deterministic predicate in any order with PL-Unit?

I want to unit test a non-deterministic predicate in Prolog with PL-Unit.
I want to "assert" that the solutions I specify in my tests are the only solutions for the predicate.
I'm not concerned about the order that each solution is specified in the test.
What the SWI-Prolog manual says:
The SWI-Prolog manual has a great section called testing non-deterministic predicates...
2.2.3 Testing non-deterministic predicates
Non-deterministic predicates succeed zero or more times. Their results are tested either using findall/3 or setof/3 followed by a value-check or using the all or set options. The following are equivalent tests:
test(member) :-
findall(X, member(X, [a,b,c]), Xs),
Xs == [a,b,c].
test(member, all(X == [a,b,c])) :-
member(X, [a,b,c]).
This is almost exactly what I need. However, for these tests to pass, the output has to be specified in the correct order: [a, b, c]. I'd like to be able to specify it in any order and still have the test pass.
An example of what I'm trying:
Let's say I'm testing this (hypothetical) predicate that has two solutions.
specialNumber(X) :-
X is 2;
X is 4.
I could write a passing unit test like so...
% PASSES!
test(specialNumber, all(X == [2, 4])) :-
specialNumber(X).
But it would fail if I swapped the order of the solutions...
% FAILS!
test(specialNumber, all(X == [4, 2])) :-
specialNumber(X).
How can I make this test pass regardless of the order that the solutions are found?
Consider using setof/3 instead of findall/3 to collect and sort .
For example, given the slightly rewritten definition of your predicate:
special_number(X) :-
( X #= 2
; X #= 4
).
We can define the following PlUnit test:
:- begin_tests(all).
test(solutions, Solutions = [2,4]) :-
setof(X, special_number(X), Solutions).
:- end_tests(all).
This test case continues to work if you rewrite your predicate for example to:
special_number(X) :-
( X #= 4
; X #= 2
).
In this case, we have:
?- findall(X, special_number(X), Ls).
Ls = [4, 2].
?- setof(X, special_number(X), Ls).
Ls = [2, 4].
As an alternative to setof/3, you can for example use:
findall/3
and then sort solutions manually with sort/2.
Related topics for you to read:
standard order of terms
bagof/3
(#<)/2
I leave adding the necessary libraries and directives that are necessary to run the example above as an exercise.

Populate a list with only one occurrence of multiple list elements

I'm new to Prolog and I am trying to understand it.
I started with some simple program, this one should:
check if an element is contained in the rest of the list
if FALSE do nothing
if TRUE add it to a second list. (only one occurrence of a char should be added to the second list).
Some examples with expected results:
?- occ([a,b,c,a,a,b,e,f,g], Y).
Y = [a,b].
?- occ([a,a,a,a,a], Y).
Y = [a].
?- occ([a,b,c,d,e,f,g], Y).
Y = [].
Here's the code I wrote, but I have some problems (it always returns true).
occ([],[]).
occ([],_Y).
occ([X|Xs],[X|Y]) :-
occ(Xs,Y),
member(X,Xs),
not(member(X,Y)),
!.
occ([_X|_Xs],_Y).
I tried using the debugger and I found that the not(member(X,Y)) is always false and in the binding section there is only X and Xs and never Y. Any advice is much appreciated! Thank you.
UPDATE
I think I solved it, here's the code:
occ([],[]).
occ([X|Xs],[X|Y]) :-
occ(Xs,Y),
member(X,Xs),
not(member(X,Y)),
!.
occ([_X|_Xs],[]).
But I'm not really sure why it works now... in the 3-th occ I changed the _Y with []..
But why does it change the results?
In this answer we use meta-predicate tpartition/4 in combination with if_/3 and (=)/3.
We define list_duplicateset/2 like this:
list_duplicateset([], []).
list_duplicateset([E|Xs0], Ys0) :-
tpartition(=(E), Xs0, Es, Xs),
if_(Es = [],
Ys0 = Ys,
Ys0 = [E|Ys]),
list_duplicateset(Xs, Ys).
First, we run a sample query taken from this answer to a similar question:
?- list_duplicateset([1,2,2,3,4,5,7,6,7], Xs).
Xs = [2,7].
Next, let's run the queries the OP gave:
?- list_duplicateset([a,b,c,a,a,b,e,f,g], Xs).
Xs = [a, b].
?- list_duplicateset([a,a,a,a,a], Xs).
Xs = [a].
?- list_duplicateset([a,b,c,d,e,f,g], Xs).
Xs = [].
Note that all queries presented above
give the expected answers and succeed deterministically.

Removing heads from lists in Prolog

I'm trying to write a predicate to remove the head from every list in list of lists and add the tails to a new list. The resulting list should be returned as the second parameter.
Here's the attempt:
construct_new(S,New) :-
New = [],
new_situation(S,New).
new_situation([],_).
new_situation([H|T], New) :-
chop(H, H1),
new_situation(T, [H1|New]).
chop([_|T], T).
You would call it like this:
construct_new([[x,x],[b,c],[d,e,f]],S).
This, however, only produces output true..
Step-by-step execution
Your query is construct_new(Input,Output), for some instanciated Input list.
The first statement in construct_new/2 unifies Output (a.k.a. New) with the empty list. Where is the returned list supposed to be available for the caller? Both arguments are now unified.
You call new_situation(Input,[])
You match the second clause new_situation([H|T],[]), which performs its task recursively (step 4, ...), until ...
You reach new_situation([],_), which successfully discards the intermediate list you built.
Solutions
Write a simple recursive predicate:
new_situation([],[]).
new_situation([[_|L]|T],[L|R]) :-
new_situation(T,R).
Use maplist:
construct_new(S,R) :-
maplist(chop,S,R).
Remark
As pointed out by other answers and comments, your predicates are badly named. construct_new is not a relation, but an action, and could be used to represent almost anything. I tend to like chop because it clearly conveys the act of beheading, but this is not an appropriate name for a relation. repeat's list_head_tail(L,H,T) is declarative and associates variables to their roles. When using maplist, the other predicate (new_situation) doesn't even need to exist...
...even though guillotine/3 is tempting.
This could be done with a DCG:
owth(Lists, Tails) :-
phrase(tails(Tails), Lists).
tails([]) --> [].
tails([T|Tails]) --> [[_|T]], tails(Tails).
Yielding these queries:
| ?- owth([[x,x],[b,c],[d,e,f]], T).
T = [[x],[c],[e,f]] ? ;
no
| ?- owth(L, [[x],[c],[e,f]]).
L = [[_,x],[_,c],[_,e,f]]
yes
(owth = Off with their heads! or, if used the other direction, On with their heads!)
If you also want to capture the heads, you can enhance it as follows:
owth(Lists, Heads, Tails) :-
phrase(tails(Heads, Tails), Lists).
tails([], []) --> [].
tails([H|Hs], [T|Tails]) --> [[H|T]], tails(Hs, Tails).
We use meta-predicate maplist/[3-4] with one of these following auxiliary predicates:
list_tail([_|Xs],Xs).
list_head_tail([X|Xs],X,Xs).
Let's run some queries!
?- maplist(list_head_tail,[[x,x],[b,c],[d,e,f]],Heads,Tails).
Heads = [x,b,d],
Tails = [[x],[c],[e,f]].
If you are only interested in the tails, use maplist/4 together with list_head_tail/3 ...
?- maplist(list_head_tail,[[x,x],[b,c],[d,e,f]],_,Tails).
Tails = [[x],[c],[e,f]].
... or, even simpler, maplist/3 in tandem with list_tail/2:
?- maplist(list_tail,[[x,x],[b,c],[d,e,f]],Tails).
Tails = [[x],[c],[e,f]].
You can also use the somewhat ugly one-liner with findall/3:
?- L = [[x,x],[b,c],[d,e,f]],
findall(T, ( member(M, L), append([_], T, M) ), R).
R = [[x], [c], [e, f]].
(OK, technically a two-liner. Either way, you don't even need to define a helper predicate.)
But definitely prefer the maplist solution that uses chop as shown above.
If you do the maplist expansion by hand, and name your chop/2 a bit better, you would get:
lists_tails([], []).
lists_tails([X|Xs], [T|Ts]) :-
list_tail(X, T),
lists_tails(Xs, Ts).
And since you can do unification in the head of the predicate, you can transform this to:
lists_tails([], []).
lists_tails([[_|T]|Xs], [T|Ts]) :-
lists_tails(Xs, Ts).
But this is identical to what you have in the other answer.
Exercise: why can't we say:
?- maplist(append([_]), R, [[x,x],[b,c],[d,e,f]]).

Prolog - Finding the longest increasing subsequence

I want to solve the following exercise in Prolog:
For a list of integers Zs, max_sequence(Zs,Xs) finds a longest increasing subsequence Xs.
Sample queries:
?- max_sequence([1,2,1,2,3,4,2,1,2,1],Xs).
Xs = [1,2,3,4]. % expected result
?- max_sequence([1,2,1,2,3,4,2,1,6,7,7,2,1,8],Xs).
Xs = [1,2,3,4,6,7,8]. % expected result
I can't understand why... but my code is wrong, the result is always false.
max_sequence(L,R) :-
cresc(L,[],R).
cresc([],[],[]).
cresc([H|T],C,[H|C]) :-
maxList(H,C),
\+ member(H,C),
cresc(T,C,C).
cresc([H|T],C,C) :-
member(H,C),
cresc(T,C,C).
cresc([H|T],C,C) :-
\+ maxList(H,C),
cresc(T,C,C).
maxList(_,[]).
maxList(N, [H|T]) :-
N>H,
maxList(N,T).
I would like to know if my approach to the problem is correct.
Thanks for any help!
TL;DR: Solve problems on a high-level: Think idiomatically; and don't reinvent the wheel :)
Use clpfd!
:- use_module(library(clpfd)).
We proceed by taking the following two steps:
We start by using the meta-predicate splitlistIfAdj/3 together with (#>=)/3:
?- splitlistIfAdj(#>=,[1,2,2,2,1,2,3,4,2,1,3,5,7,1],Zss).
Zss = [[1,2],[2],[2],[1,2,3,4],[2],[1,3,5,7],[1]].
We are only interested in sublists of maximum size. max_of_by/3 can exclude all other ones:
?- max_of_by(Xs,[[1,2],[2],[2],[1,2,3,4],[2],[1,3,5,7],[1]],length).
Xs = [1,2,3,4]
; Xs = [1,3,5,7].
That's it! Let's put it together and define list_longest_ascending_sublist/2:
list_longest_ascending_sublist(Xs,Zs) :-
splitlistAdjIf(#>=,Xs,Yss),
max_of_by(Zs,Yss,length).
Sample queries:
?- list_longest_ascending_sublist([1,2,2,2,1,2,3,4,2,1,3,5,7,1],Zs).
Zs = [1,2,3,4]
; Zs = [1,3,5,7].
?- list_longest_ascending_sublist([1,2,2,3,4,5,6,2,1,2,3,4,2,1,3,5,7,1],Zs).
Zs = [2,3,4,5,6].
I can't understand your approach at all, but using Trace command in swi-prolog you can see your program execution step by step to see where it fails. Try it and you will see what's wrong with your code.
Anyway this could be one possible solution: starting from the first element of the list you should simply collect a list until elements are increasing, keeping also the length of this sublist, this is the first candidate. Then start again collecting a new list and its length, and if is longer than the candidate, you switch them, and so on..
Here you can find the code: max_seqs , the first part.

Prolog - copy a piece of list

I need to duplicate list in prolog.
I have list:
L = [a(string1,value1),a(string2,value2),a(string3,value3),a(string4,value4)].
Output will be: L = [string1, string2, string3, string4].
How can I do this?
I can copy whole list by code:
copy([],[]).
copy([H|L1],[H|L2]) :- copy(L1,L2).
I have tried something like:
copy2([],[]).
copy2([H|L1],[K|L2]) :- member(f(K,_),H), copy2(L1,L2).
But it does not work properly.
But I need only strings from my original list. Can anyone help?
pattern matching is used to decompose arguments: you can do
copy([],[]).
copy([a(H,_)|L1],[H|L2]) :- copy(L1,L2).
It is uncommon to use a structure a/2 for this purpose. More frequently, (-)/2 is used for this. Key-Value is called a (key-value) pair.
Also the name itself is not very self-revealing. This is no copy at all. Instead, start with a name for the first argument, and then a name for the second. Lets try: list_list/2. The name is a bit too general, so maybe apairs_keys/2.
?- apairs_keys([a(string1,value1),a(string2,value2)], [string1, string2]).
Here are some definitions for that:
apairs_keys([], []).
apairs_keys([a(K,_)|As], [K|Ks]) :-
apairs_keys(As, Ks).
Or, rather using maplist:
apair_key(a(K,_),K).
?- maplist(apair_key, As, Ks).
Or, using lambdas:
?- maplist(\a(K,_)^K^true, As, Ks).
Declarative debugging techniques
Maybe you also want to understand how you can quite rapidly localize the error in your original program. For this purpose, start with the problematic program and query:
copy2([],[]).
copy2([H|L1],[K|L2]) :-
member(f(K,_),H),
copy2(L1,L2).
?- copy2([a(string1,value1),a(string2,value2),a(string3,value3),a(string4,value4)], [string1, string2, string3, string4]).
false.
Now, generalize the query. That is, replace terms by fresh new variables:
?- copy2([a(string1,value1),a(string2,value2),a(string3,value3),a(string4,value4)], [A, B, C, D]).
false.
?- copy2([a(string1,value1),a(string2,value2),a(string3,value3),a(string4,value4)], L).
false.
?- copy2([a(string1,value1),B,C,D], L).
false.
?- copy2([a(string1,value1)|J], L).
false.
?- copy2([a(S,V)|J], L).
false.
?- copy2([A|J], L).
A = [f(_A,_B)|_C], L = [_A|_D]
; ... .
So we hit bottom... It seems Prolog does not like a term a/2 as first argument.
Now, add
:- op(950,fx, *).
*_.
to your program. It is kind of a simplistic debugger. And generalize the program:
copy2([],[]).
copy2([H|L1],[K|L2]) :-
member(f(K,_),H),
* copy2(L1,L2).
Member only succeeds with H being of the form [_|_]. But we expect it to be a(_,_).