Permutation predicate in Prolog - recursion

I have written the following in Prolog (I am using version 7.4.0-rc1), trying to define a predicate insertPermutation/2 which is true if and only if both arguments are lists, one a permutation of the other.
delete(X,[X|T],T). % Base case, element equals head.
delete(X,[A|B],[A|C]) :- delete(X,B,C). % And/or repeat for the tail.
insert(X,Y,Z) :- delete(X,Z,Y). % Inserting is deletion in reverse.
insertPermutation([],[]). % Base case.
insertPermutation([H|T],P) :- insertPermutation(Q,T), insert(H,Q,P). % P permutation of T, H inserted.
I have already been made aware that delete is not a good name for the above helper predicate. We are required to write these predicates, and we cannot use the built-in predicates. This is why I wrote the above code in this way, and I chose the name I did (because I first wrote it to delete an element). It is true if and only if the third argument is a list, equal to the list in the second argument with the first instance of the first argument removed.
The insertPermutation predicate recursively tests if P equals a permutation of the tail of the first list, with the head added in any position in the permutation. This way it works to the base case of both being empty lists.
However, the permutation predicate does not behave the way I want it to. For instance, to the query
?- insertPermutation([1,2,2],[1,2,3]).
Prolog does not return false, but freezes. To the query
?- insertPermutation(X,[a,b,c]).
Prolog responds with
X = [a, b, c] ;
X = [b, a, c] ;
X = [c, a, b] ;
X = [a, c, b] ;
X = [b, c, a] ;
X = [c, b, a] ;
after which it freezes again. I see these problems are related, but not how. Can someone point out what case I am missing?
Edit: Two things, this is homework, and I need to solve this problem using an insert predicate. I wrote this one.

The answer is to change the last line
% P permutation of T, H inserted.
insertPermutation([H|T],P) :-
insertPermutation(Q,T),
insert(H,Q,P).
% P permutation of T, H inserted.
insertPermutation(P,[H|T]) :-
insertPermutation(Q,T),
insert(H,Q,P).
The use cases only needed to check if the first element is a permutation of the latter, not the other way around (or vice versa). Anti-climatic, but the answer to my problem.

Related

How to properly iterate through two-dimensions array and sum all the lengths of elements?

I've encountered a problem when trying to iterate through two dimension array and summing up the lengths of all elements inside in prolog.
I've tried iterating through a simple 1D array and result was just as expected. However, difficulties appeared when I started writing the code for 2D array. Here's my code :
findsum(L):-
atom_row(L, Sum),
write(Sum).
atom_row([Head|Tail], Sum) :-
atom_lengths(Head, Sum),
atom_row(Tail, Sum).
atom_row([], 0).
atom_lengths([Head|Tail], Sum):-
atom_chars(Head, CharList),
length(CharList, ThisLenght),
atom_lengths(Tail, Temp),
Sum is Temp + ThisLenght,
write(ThisLenght).
atom_lengths([], 0).
For example, sum of the elements in array [[aaa, bbbb], [ccccc, dddddd]] should be equal to 18. And this is what I get:
?- findsum([[aaa, bbbb], [ccccc, dddddd]]).
436
false.
The output comes from write(ThisLength) line after each iteration.
Typically it helps (a lot) by splitting the problem into simpeler sub-problems. We can solve the problem, for example, with the following three steps:
first we concatenate the list of lists into a single one-dimension list, for example with append/2;
next we map each atom in that list to the length of that atom, with the atom_length/2 predicate; and
finally we sum up these values, for example with sum_list/2.
So the main predicate looks like:
findsum(LL, S) :-
append(LL, L),
maplist(atom_length, L, NL),
sumlist(NL, S).
Since maplist/3 is a predicate defined in the library(apply), we thus don't need to implement any other predicates.
Note: You can see the implementions of the linked predicates by clicking on the :- icon.
For example:
?- findsum([[aaa, bbbb], [ccccc, dddddd]], N).
N = 18.

Prolog: Check predicate against every item in the list

Basically, I want to be able to check to see if at least one value in a list satisfies some predicate.
What I have so far:
need(x,y).
check_list(X,[H|T]) :-
need(H,X).
And so this works fine so long as I only have one value in the list. I'm not sure how to make it check the other values. When I try and use recursion I eventually find an element that satisfies the second predicate but it then goes back up the stack which will eventually cause it to be false.How can I make it 'break' essentially?
The backtracking you are seeing during recursion is Prolog attempting to find more ways for the predicate to succeed. This is a fundamental Prolog behavior and is what makes it useful. It seeks to find all of the solutions.
In your case, you only want to confirm one solution to the problem of, An element in the list that meets a specific criterion. For this, you could use a cut:
check_list(X, [H|_]) :-
need(X, H), !. % Don't backtrack after success
check_list(X, [_|T]) :-
check_list(X, T).
Or you could use once/1 which is specifically designed to handle cases where you only want a single solution:
check_list(X, [H|_]) :-
need(X, H).
check_list(X, [_|T]) :-
check_list(X, T).
check_list_once(X, L) :- once(check_list(X, L)).
Here is an example of what you can do.
I want to check is numbers are odd.
is_even(X) :-
X mod 2 =:= 0.
check_list(L, CL) :-
include(is_even, L, CL).
with result
?- check_list([1,2,3,4,5], L).
L = [2, 4].
?- check_list([1,3,5], L).
L = [].
You can use simple recursion:
need(x,y).
check_list(X,[H|T]) :-
( need(H,X) -> true;
check_list(X,T) ).
You can see in the examples below that this definition is deterministic:
?- check_list(y,[1,2,3]).
false.
?- check_list(y,[x,2,3]).
true.
?- check_list(y,[1,2,x]).
true.
?- check_list(Y,[1,2,x]).
Y = y.
?- check_list(Y,[1,2,3]).
false.
?- check_list(Y,[1,x,3]).
Y = y.
?- check_list(Y,[1,X,3]).
Y = y,
X = x.
?- check_list(Y,[1,2,3]), Y = x.
false.
?- check_list(Y,[1,2,3]), Y = y.
false.
?- check_list(Y,[1,2,3]).
false.
?- check_list(Y,[1,2,x]), Y = y.
Y = y.
Though if you want your queries to have uninstantiated variables e.g check_list(Y,[1,2,x]). and you add another fact need(x,z). Then:
?- check_list(Y,[1,2,x]).
Y = y.
Returns only one result and not Y = z. You could use if_/3 from library reif if you want a better definition of check_list/3.

How to return duplicates from list in Prolog

I am trying to write a predicate which deletes all the unique elements of a list (and return the duplicates) like this:
?- delete_unique([a, b, a, a], L).
L = [a, a, a]
Although my code isn't working.
delete_unique([],[]).
delete_unique([H|T],[H|Solution]):-
member(H,Solution),!,
delete_unique(T,Solution).
delete_unique([H|T],[H|Solution]):-
member(H,T),
delete_unique(T,Solution).
delete_unique([H|T],Solution):-
%%not(member(H,Solution)),
%%not(member(H,T)),
delete_unique(T,Solution).
To remove duplicates, if the order doesn't matter, the easiest is to use sort/2:
?- sort([a,a,b,b,c], X).
X = [a, b, c].
?- sort([c,c,a,a,b], X).
X = [a, b, c].
Of course, you see that the original order of the elements is lost. More importantly, this only guarantees to be correct if the list you are sorting is already ground (no free variables in it).

Simple functions for SML/NJ

I was required to write a set of functions for problems in class. I think the way I wrote them was a bit more complicated than they needed to be. I had to implement all the functions myself, without using and pre-defined ones. I'd like to know if there are any quick any easy "one line" versions of these answers?
Sets can be represented as lists. The members of a set may appear in any order on the list, but there shouldn't be more than one
occurrence of an element on the list.
(a) Define dif(A, B) to
compute the set difference of A and B, A-B.
(b) Define cartesian(A,
B) to compute the Cartesian product of set A and set B, { (a, b) |
a∈A, b∈B }.
(c) Consider the mathematical-induction proof of the
following: If a set A has n elements, then the powerset of A has 2n
elements. Following the proof, define powerset(A) to compute the
powerset of set A, { B | B ⊆ A }.
(d) Define a function which, given
a set A and a natural number k, returns the set of all the subsets of
A of size k.
(* Takes in an element and a list and compares to see if element is in list*)
fun helperMem(x,[]) = false
| helperMem(x,n::y) =
if x=n then true
else helperMem(x,y);
(* Takes in two lists and gives back a single list containing unique elements of each*)
fun helperUnion([],y) = y
| helperUnion(a::x,y) =
if helperMem(a,y) then helperUnion(x,y)
else a::helperUnion(x,y);
(* Takes in an element and a list. Attaches new element to list or list of lists*)
fun helperAttach(a,[]) = []
helperAttach(a,b::y) = helperUnion([a],b)::helperAttach(a,y);
(* Problem 1-a *)
fun myDifference([],y) = []
| myDifference(a::x,y) =
if helper(a,y) then myDifference(x,y)
else a::myDifference(x,y);
(* Problem 1-b *)
fun myCartesian(xs, ys) =
let fun first(x,[]) = []
| first(x, y::ys) = (x,y)::first(x,ys)
fun second([], ys) = []
| second(x::xs, ys) = first(x, ys) # second(xs,ys)
in second(xs,ys)
end;
(* Problem 1-c *)
fun power([]) = [[]]
| power(a::y) = union(power(y),insert(a,power(y)));
I never got to problem 1-d, as these took me a while to get. Any suggestions on cutting these shorter? There was another problem that I didn't get, but I'd like to know how to solve it for future tests.
(staircase problem) You want to go up a staircase of n (>0) steps. At one time, you can go by one step, two steps, or three steps. But,
for example, if there is one step left to go, you can go only by one
step, not by two or three steps. How many different ways are there to
go up the staircase? Solve this problem with sml. (a) Solve it
recursively. (b) Solve it iteratively.
Any help on how to solve this?
Your set functions seem nice. I would not change anything principal about them except perhaps their formatting and naming:
fun member (x, []) = false
| member (x, y::ys) = x = y orelse member (x, ys)
fun dif ([], B) = []
| dif (a::A, B) = if member (a, B) then dif (A, B) else a::dif(A, B)
fun union ([], B) = B
| union (a::A, B) = if member (a, B) then union (A, B) else a::union(A, B)
(* Your cartesian looks nice as it is. Here is how you could do it using map: *)
local val concat = List.concat
val map = List.map
in fun cartesian (A, B) = concat (map (fn a => map (fn b => (a,b)) B) A) end
Your power is also very neat. If you call your function insert, it deserves a comment about inserting something into many lists. Perhaps insertEach or similar is a better name.
On your last task, since this is a counting problem, you don't need to generate the actual combinations of steps (e.g. as lists of steps), only count them. Using the recursive approach, try and write the base cases down as they are in the problem description.
I.e., make a function steps : int -> int where the number of ways to take 0, 1 and 2 steps are pre-calculated, but for n steps, n > 2, you know that there is a set of combinations of steps that begin with either 1, 2 or 3 steps plus the number combinations of taking n-1, n-2 and n-3 steps respectively.
Using the iterative approach, start from the bottom and use parameterised counting variables. (Sorry for the vague hint here.)

Trying to understand a recursive prolog procedure?

This was given as an example in a professor's lecture:
append([ ], A, A).
append([A|B], C, [A|D]) :- append(B,C,D).
Build a list:
?- append([a],[b],Y).
Y = [ a,b ]
Break a list into constituent parts:
?- append(X,[b],[a,b]).
X = [ a ]
?- append([a],Y,[a,b]).
Y = [ b ]
I've spent 3 hours trying to grasp it and can't. Hadn't had any trouble with any prolog concepts preceding this slide. There is no further explanation provided, no other information. This is all. If someone could walk me through how this procedure works, I would love them til death do us part.
The first thing to understand is the :- operator.
this_will_be_true :- if_this_is_true
Basically, whatever is on the right of :- is a precondition. A good example is:
sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y).
This basically means that X and Y are siblings if there exists a parent Z such that Z is the parent of both X and Y.
append([ ], A, A).
This line basically means that appending something to an empty list returns the something. It's the base case in the recursion.
append([A|B], C, [A|D]) :- append(B,C,D).
This line means that appending C to an existing list with A and B returns a list with A and D given that appending C to B returns D.
Build a list:
?- append([a],[b],Y).
Y = [ a,b ]
So, what's going on here is that Prolog returns the only possible value of Y that satisfies the two rules given the two initial values. Let's think about how this happens. This would need to first be evaluated by the second rule. So [A|B] is [a] and C is [b].
So with [A|B] we have to go back to the first rule because B is empty list (it is [ ]). The first rule basically states that we can write [a] as [a|[ ]] and they are the same thing. So now we can go back to the second rule. A is a, B is [ ], and C is [b].
So now let's check the precondition of append(B, C, D). This is append([ ], [b], D). Once again, using the first rule, we can see that D is also [b].
So Y, by the second rule definition, is [A|D]. Now that we know D is [b], we know that Y is [a, b].
I'll only do one of the breaking apart since they're basically the same thing.
?- append(X,[b],[a,b]).
X = [ a ]
So here, Prolog is going to return the only possible value of X so that the statement returns true. Let's take a look at the second rule. So we know that [a, b] is [A|D]. This means that A is a and D is [b]. We also know that C is [b]. So now, we need to look at the precondition to figure out what B is. append(B, C, D) translates to append(B, [b], [b]). Now, using the first rule, we know that B has to be [ ]. So now we know that [A|B] is [a|[ ]] which is the same as [a]. Therefore, X must be [a].
I hope this was a detailed enough explanation.
Below is my own understanding.
Your code describes the append operation of List.
At first here's an abbrevation that helps you to understand what is a list in prolog and what's the meaning of |:
[X1|[...[Xn|[]] = [X1,...Xn]
And append(A, B, C) means appending list B to A results in C.
Append A to empty list results in A:
append([ ], A, A).
If you want to append Y to X, say append(X, Y, _). Unless X is [], prolog would not know anything to do. You have to tell the rules to prolog by saying:
append([A|B], C, [A|D]) := append(B, C, D)
Then prolog will try to split X into form [A|B]. Then Y would be A|D where D is the list defined by C appended to B. append(B, C, D) is the way we tell prolog about this fact.

Resources