I need to write a predicate f(L,R) that succeeds if and only if L is a list containing all terms in R that are not lists.
For example:
f(L,[1,2,3,[4,5,6],[[7,8,9]],[]]).
Should give:
L = [1,2,3,4,5,6,7,8,9]
I wrote a predicate that gives the following result instead:
L = [1,2,3,4,5,6,7,8,9,[]]
Empty lists should not be present in the result. My predicate is the following:
f([],[]).
f(V,[H|T]):- H = [_|_] -> append(L,R,V),
f(L,H), f(R,T),!;
V = [H1|T1], H1=H, f(T1,T).
I have two doubts. First of all, the empty lists should not be present in the result. Also I don't know why it does not work if I don't put the cut (!). In fact, if I don't put the cut it gives me the result as above, but if I ask for another result it loops forever. I really don't understand why this should loops.
To remove the empty list, handle that case (discard it).
About the loop: I think the cause could be that you're calling append(L,R,V) with all arguments not instantiated: move append after the recursive calls.
Finally, maybe you don't use rightly the 'if then else' construct: I've indented using the usual SWI-Prolog source style, using indentation to highlight 'sequential' calls
f([], []).
f(V, [H|T]) :-
( H = [] % if H = []
-> f(V, T) % then discard
; H = [_|_] % else if H is list
-> f(L,H), % flat head
f(R,T), % ...
append(L,R,V)
; V = [H|T1], % else
f(T1,T) % ...
).
Related
I'm working on this prolog assignment where I must parse an user-inputted list of string characters (specifically "u"), and determine if all the elements are equal to the string "u". If they are, then it returns the number of elements, if not, it returns false. For example:
uA(-Length,+String,+Leftover) //Prototype
?- uA(L,["u","u","u"],[]).
L = 3 .
?- uA(L,["u","u","d"],[]).
false.
I have a decent grasp on how prolog works, but I'm confused about how lists operate. Any help would be greatly appreciated. Thanks!
Edit: I made some headway with the sort function (thank you!) but I've run into a separate problem.
uA(Length, String) :-
sort(String, [_]),
member("u", String),
length(String, Length).
This does mostly what I need it to, however, when I run it:
?- uA(L, ["u", "u", "u"]).
L = 3 ;
L = 3 ;
L = 3.
Is there any way to make it such that it only prints L = 3 once? Thanks!
If you want to state that all list items are equal, there is no need to sort the list first.
Simply use library predicate maplist/2 together with the builtin predicate (=)/2:
?- maplist(=(X), Xs).
Xs = []
; Xs = [X]
; Xs = [X, X]
; Xs = [X, X, X]
; Xs = [X, X, X, X]
… % ... and so on ...
First of all, be careful with double-quoted terms in Prolog. Their interpretation depends on the value of the standard double_quotes flag. The most portable value of this flag is codes, which makes e.g. "123" being interpreted as [49,50,51]. Other possible values of this flag are atom and chars. Some Prolog systems, e.g. SWI-Prolog, also support a string value.
But back to your question. A quick way to check that all elements in a ground list are equal is to use the standard sort/2 predicate (which eliminates duplicated elements). For example:
| ?- sort(["u","u","u"], [_]).
yes
| ?- sort(["u","u","d"], [_]).
no
As [_] unifies with any singleton list, the call only succeeds if the the sorting results in a list with a single element, which only happens for a non-empty ground list if all its elements are equal. Note that this solution is independent of the value of the double_quotes flag. Note also that you need to deal with an empty list separately.
My approach is to check if every element in the list is the same or not (by checking if the head of the list and it's adjacent element is the same or not). If same then return True else false. Then calculate the length of every element is the same in the list.
isEqual([X,Y]):- X == Y , !.
isEqual([H,H1|T]):- H == H1 , isEqual([H1|T]).
len([],0).
len([_|T],L):- len(T,L1) , L is L1+1.
goal(X):- isEqual(X) , len(X,Length) , write('Length = ') , write(Length).
OUTPUT
?- goal(["u","u","u"]).
Length = 3
true
?- goal(["u","u","a"]).
false
you can do it this way. Hope this helps you.
I need to convert a list of elements into a list of lists.
For example, if i have the list [1,2,3,4] the output must be [[1],[2],[3],[4]], one element per list.
create([],_, _, _).
create([H|T], Aux, X, Result) :-
append([H], Aux, X),
Result = [X],
create(T, X, _, Result).
I always get false... is this even possible to do?
Another possibility to define this relation is by using DCGs. They yield easily readable code when describing lists. Let's stick with the name singletons as suggested by #false in the comments:
singletons([]) --> % the empty list
[]. % is empty
singletons([H|T]) --> % the head of a nonempty list
[[H]], % is a list on its own
singletons(T). % and so is the tail
You can query this directly with phrase/2:
?- phrase(singletons([1,2,3,4]),X).
X = [[1],[2],[3],[4]]
Or write a wrapper-predicate with phrase/2 as the single goal:
singletons(L,Ls) :-
phrase(singletons(L),Ls).
And query that:
?- singletons([1,2,3,4],Ls).
Ls = [[1],[2],[3],[4]]
The predicate also works the other way around:
?- singletons(L,[[1],[2],[3],[4]]).
L = [1,2,3,4] ? ;
no
As well as the most general query:
?- singletons(L,Ls).
L = Ls = [] ? ;
L = [_A],
Ls = [[_A]] ? ;
L = [_A,_B],
Ls = [[_A],[_B]] ?
...
Alternatively you can also define a simple predicate that describes a relation between an arbitrary element and itself in brackets and then use maplist/3 from library(apply) to apply it on every element of a list:
:- use_module(library(apply)).
embraced(X,[X]).
singletons(L,Ls) :-
maplist(embraced,L,Ls).
This version yields the same results for the above queries. However, it is more efficient. To see that consider the following query from above:
?- singletons(L,[[1],[2],[3],[4]]).
L = [1,2,3,4]
Above you had to enter ; to make Prolog search for further solutions and subsequently fail (indicated by no). With this version there are no unnecessary choice points left and Prolog is succeeding deterministically for the query.
Try this
create([],[]).
create([H|T],[[H]|T2]):- create(T,T2).
I tried
?- create([1,2,3,4],X).
and the result was
X = [[1], [2], [3], [4]].
I'm trying to write a palindrome function in Prolog. I know I could just use something like
palindrome(List) :- reverse(List, List).
But I'm trying to figure out a way without using the built in reverse. I've created my own reverse rule:
rev([], []).
rev([H|T], X) :- rev(T, Y), append(Y, [H], X).
And what I'd like is, given a list, say [a,b,c,d], I'd like to do something like "X = rev([a,b,c,d]), but I'm really not sure whether this is possible in Prolog.
If it is, the way I would write my palindrome function would be something like:
palindrome(List) :- append(L1, rev(L1), List).
Is it possible to do what I'm trying to do - i.e. X = rev([a,b,c,d])?.
Thanks.
Palindromes are lists that read the same from front to back and from back to front. So the example you have given, [a,b,c,d] and it's reversal, constitute a palindrome if the first is directly followed by the second: [a,b,c,d,d,c,b,a]. Since you are trying to describe specific kinds of lists, it is very tempting to use Prolog DCGs for the task. With them you can define palindromes like so:
palindrome(X) :-
phrase(palindrome,X).
palindrome --> % base case for even number of elements
[].
palindrome --> % base case for odd number of elements
[A].
palindrome --> % general case: a palindrome is
[A], % some element A...
palindrome, % ... followed by a palindrome ...
[A]. % ... followed by element A
The most general query is producing palindromes with variables for each position:
?- palindrome(P).
P = [] ? ;
P = [_A] ? ;
P = [_A,_A] ? ;
P = [_A,_B,_A] ? ;
P = [_A,_B,_B,_A] ? ;
P = [_A,_B,_C,_B,_A] ?
...
Or alternatively you can test if a specific list is a palindrome:
?- palindrome("rats live on no evil star").
yes
?- palindrome([1,2,3,2,1]).
yes
?- palindrome([a,b,c,d]).
no
?- palindrome([a,b,c,d,d,c,b,a]).
yes
If you insist on using list reversal you can define the relation like so:
list([]) -->
[].
list([X|Xs]) -->
[X],
list(Xs).
invlist([]) -->
[].
invlist([X|Xs]) -->
invlist(Xs),
[X].
palindrome --> % a paindrome is
list(L), % a list followed
invlist(L). % by its reversal
palindrome --> % a palindrome is
list(L), % a list followed by
[_A], % some element
invlist(L). % then by the reversed list
The first of the above queries produces the answers in a different order now, namely the solutions with an even number of elements first:
?- palindrome(P).
P = [] ? ;
P = [_A,_A] ? ;
P = [_A,_B,_B,_A] ? ;
P = [_A,_B,_C,_C,_B,_A] ?
...
The other example queries yield the same result. However, the first definition seems to be clearly preferable to me. Not only because it is shorter as there is no need for additional DCG rules but also because it is producing the results in a fair order: empty list, one element, two elements, ... With the second version you get all the lists with an even number of elements first and there are infinitely many of those. So you never get to see a solution with an odd number of elements with the most general query.
So i just got in ML programming and I found this excercise in a book. The excercise says to build a recursive function that takes an integer and a list. If L=[a1,a2,a3] then the desired result is [ai+1,ai+2,...,an,a1,a2,...,ai]. So I wrote a function and after a lot of hours I narrowed the errors down to one which I can't understand. Here is my function:
fun cycle L i =
if i = 0 then L
else (cycle tl(L) (i-1)) # [hd(L)];
I will upload an image with the error that i get so someone can explain to me what the interpreter is trying to say to me.
The numbers next to the "a" just show the order of these elements in the list.So for L=[1,2,3,4,5] and for i = 2, the desire result is the List L=[3,4,5,1,2]. I don't think that the type of list is essential in this problem. Hope this further explanation helped
It's a syntactic problem with the recursive call cycle tl(L) (i-1).
In SML, the syntax for function application is juxtaposition, not parentheses. In your case tl(L) indeed calls the function tl with argument L, but that's equivalent to just tl L. The parentheses are redundant and, as such, ignored.
Now, if you replace the minimal version within your original call, you'll get this: cycle tl L (i-1). It's calling cycle with three arguments, instead of just two.
The correct way of writing it would be: cycle (tl L) (i-1).
Ionuț already gave a sufficient answer to the syntax problem; here are some further suggestions:
Use pattern matching rather than hd and tl.
Consider the base cases; what are the simplest sub-problems you can think of? E.g. cycling the empty list will always give the empty list regardless of n, and cycling L 0 times will always give L back. Having both base cases as patterns helps.
Consider the recursive case; the top element (assuming it exists) is cycled and i is reduced by one, until eventually i is 0 or L is empty. Because the second base case catches the empty list, we can freely assume that L is non-empty here, in which case it will match the pattern x::xs.
fun cycle 0 xs = xs
| cycle i [] = []
| cycle i (x::xs) = cycle (i-1) (xs # [x])
Depending on whether 0 <= i and i <= length xs are preconditions for the function or not, you may want to handle these once before activating the main recursion, e.g. by wrapping the function above:
fun cycle i ys =
let fun fun cycle' 0 xs = xs
| cycle' i [] = []
| cycle' i (x::xs) = cycle' (i-1) (xs # [x])
in
if 0 <= i andalso i <= length xs
then cycle' i ys
else raise Domain
end
The main operation, namely xs # [x] is terribly inefficient, since its running time is proportional to the length of xs and is activated n times. So the running time of cycle becomes O(n • |L|) when something like O(min(n,|L|)) should be achievable.
You could probably make a much faster version if you store the cycled elements in a separate list, without using #, and combine the remaining elements with this list after the elements have been cycled. Depending on what you felt about 0 <= i and i <= length xs, you may run into problems with the following test case:
val cycle_test_1 = (cycle 5 [1,2,3,4] = [2,3,4,1])
I'm trying to create a predicate in Prolog that takes a list and returns only one copy of the adjacent duplicates of the list.
for example:
?- adj_dups([a,b,a,a,a,c,c],R).
R=[a,c]
I think I need two base cases:
adj_dups([],[]). % if list is empty, return empty list
adj_dups([X],[]). % if list contains only one element, return empty list (no duplicates).
then for the recursive part, I need to compare the head with the head of the tail, and then go recursively on the tail of the list.
This is what I came up with so far, but it doesn't work!
adj_dups([X,X|T],[X|R]):- adj_dups([X|T],R). % if the list starts with duplicates
adj_dups([X,Y|T],R):- X \= Y, adj_dups([X|T],R). % if the list doesn't start wih duplicates
How can I fix it so I can get the right result?
Edit:
I'll list some examples to help you all understand my problem.
How the code supposed to behave:
?- adj_dups([a,c,c,c,b],R).
R = [c]
?- adj_dups([a,b,b,a,a],R).
R = [b,a]
?- adj_dups([a,b,b,a],R).
R = [b]
How my code is behaving:
?- adj_dups([a,c,c,c,b],R).
R = []
?- adj_dups([a,b,b,a,a],R).
R = [a,a]
?- adj_dups([a,b,b,a],R).
R = [a]
Thank you.
I find ambiguous this specification
only one copy of the adjacent duplicates of the list
as it doesn't clarify what happens when we have multiple occurrences of the same duplicate symbol.
adj_dups([],[]).
adj_dups([X,X|T],[X|R]) :-
skip(X,T,S),
adj_dups(S,R),
\+ memberchk(X,R),
!.
adj_dups([_|T],R) :- adj_dups(T,R).
skip(X,[X|T],S) :- !, skip(X,T,S).
skip(_,T,T).
This yields
?- adj_dups([a,a,c,c,a,a],R).
R = [c, a].
Comment the + memberchk line to get instead
?- adj_dups([a,a,c,c,a,a],R).
R = [a, c, a].
Let's look at what happens when you try a simpler case:
adj_dups([a,b,b,a],R).
The first three predicates don't match, so we get:
adj_dups([X,Y|T],R):- X \= Y, adj_dups([X|T],R).
This is the problematic case: X is bound to a, Y is bound to b.
It will then call adj_dups([a,b,a],R), binding T to [b,a], which only has a single b. Effectively, you have now removed the duplicate b from the list before it could be processed.
Let's create a few auxiliary predicates first - especially a predicate that filters an element from a list. Then, in the recursive part, there are two cases:
If the first element occurs in the tail of the list being processed, it is duplicated; we need to return that first element followed by the processed tail. Processing the tail consists of removing that first element from it, then check the tail for duplicates.
The second case is much simpler: if the first element does not occur in the tail, we simply apply adj_dups to the tail and return that. The first element was never duplicated, so we forget about it.
% Filter the element X from a list.
filter(X,[],[]).
filter(X,[X|T],R) :- filter(X,T,R).
filter(X,[Y|T],[Y|R]) :- X \= Y, filter(X,T,R).
% Return "true" if H is NOT a member of the list.
not_member(H,[]).
not_member(H,[H|T]):-fail.
not_member(H,[Y|T]):-H \= Y, not_member(H,T).
% Base cases for finding duplicated values.
adj_dups([],[]). % if list is empty, return empty list
adj_dups([X],[]). % if list contains only one element, return empty list (no duplicates).
% if H1 is in T1 then return the H1 followed by the adj_dups of (T1 minus H1).
% if H1 is not in T1 then return the adj_dups of T1.
adj_dups([H1|T1],[H1|T3]):-member(H1,T1), filter(H1,T1,T2), adj_dups(T2,T3).
adj_dups([H1|T1],T3):-not_member(H1, T1), adj_dups(T1,T3).
This gives R=[a,b] for the input [a,b,b,a], and R=[a,c] for your example input [a,b,a,a,a,c,c].