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]].
Again a Prolog beginner :-}
I build up a list element by element using
(1)
member(NewElement,ListToBeFilled).
in a repeating call,
(2)
ListToBeFilled = [NewElement|TmpListToBeFilled].
in a recursive call like
something(...,TmpListToBeFilled).
A concrete example of (2)
catch_all_nth1(List, AllNth, Counter, Result) :-
[H|T] = List,
NewCounter is Counter + 1,
(
0 is Counter mod AllNth
->
Result = [H|Result1]
;
Result = Result1
),
catch_all_nth1(T,AllNth,NewCounter,Result1),
!.
catch_all_nth1([], _, _, _).
As result I get a list which looks like
[E1, E2, E3, ..., Elast | _G12321].
Of course, the Tail is a Variable. [btw: are there better method to fill up the
list, directly avoiding the "unassigned tail"?]
I was now looking for a simple method to eliminate the "unassigned tail".
I found:
Delete an unassigned member in list
there it is proposed to use:
exclude(var, ListWithVar, ListWithoutVar),!,
[Found this too, but did not help as I do not want a dummy element at the end
Prolog list has uninstantiated tail, need to get rid of it ]
What I noticed is that using length\2 eliminate the "unassigned tail", too, and in addtion
the same List remains.
My Question is: How does it work? I would like to use the mechanism to eliminate the unassigned tail without using a new variable... [in SWI Prolog 'till now I did not get the debugger
entering length() ?!]
The example:
Z=['a','b','c' | Y],
X = Z,
write(' X '),write(X),nl,
length(X,Tmp),
write(' X '),write(X),nl.
13 ?- test(X).
X [a,b,c|_G3453]
X [a,b,c]
X = [a, b, c] .
I thought X, once initialized can not be changed anymore and you need
a new variable like in exclude(var, ListWithVar, ListWithoutVar).
Would be happy if someone explain the trick to me...
Thanks :-)
You're right about the strange behaviour: it's due to the ability of length/2 when called with unbound arguments
The predicate is non-deterministic, producing lists of increasing length if List is a partial list and Int is unbound.
example:
?- length([a,b,c|X],N).
X = [],
N = 3 ;
X = [_G16],
N = 4 ;
X = [_G16, _G19],
N = 5 ;
...
For your 'applicative' code, this tiny correction should be sufficient. Change the base recursion clause to
catch_all_nth1([], _, _, []).
here are the results before
4 ?- catch_all_nth1([a,b,c,d],2,1,R).
R = [b, d|_G75].
and after the correction:
5 ?- catch_all_nth1([a,b,c,d],2,1,R).
R = [b, d].
But I would suggest instead to use some of better know methods that Prolog provide us: like findall/3:
?- findall(E, (nth1(I,[a,b,c,d],E), I mod 2 =:= 0), L).
L = [b, d].
I think this should do it:
% case 1: end of list reached, replace final var with empty list
close_open_list(Uninstantiated_Var) :-
var(Uninstantiated_Var), !,
Uninstantiated_Var = '[]'.
% case 2: not the end, recurse
close_open_list([_|Tail]) :-
close_open_list(Tail).
?- X=[1,2,3|_], close_open_list(X).
X = [1, 2, 3].
Note that only variable X is used.. it simply recurses through the list until it hits the var at the end, replaces it with an empty list, which closes it. X is then available as a regular 'closed' list.
Edit: once a list element has been assigned to something specific, it cannot be changed. But the list itself can be appended to, when constructed as an open list ie. with |_ at the end. Open lists are a great way to build up list elements without needing new variables. eg.
X=[1,2,3|_], memberchk(4, X), memberchk(5,X).
X = [1, 2, 3, 4, 5|_G378304]
In the example above, memberchk tries tries to make '4', then '5' members of the list, which it succeeds in doing by inserting them into the free variable at the end in each case.
Then when you're done, just close it.
I'm attempting to make a predicate that takes a list of pairs and, if it finds the key in the list it will remove that item from the list and return the rest. However, it also needs to return the full list if the key given does not exist.
unmap(K, M1, M2):-
select(E, M1, MM1),
select(E, [(K, _)], K1),
unmap(MM1, K1, M2).
unmap(X, _, X).
Called with:
unmap(key1, [(key1, value1),(key2, value2),(key3, value3)], R).
Results in:
R = [(key2, value2), (key3, value3)]
Works, but theres a problem. I'm trying to make it return the identical list thats given if the key1 does not exist. Here's what it returns:
Calling:
unmap(key4, [(key1, value1),(key2, value2),(key3, value3)], R).
Returns:
R = key4
I think it's something to do with my terminating rule, but I'm not sure how to go about fixing it. Thanks very much in advance for all that can help.
Of course, you can do it with logical-purity! Here's how...
Let's call the actual relation pairs_key_unmapped/3. That's a somewhat more descriptive name. unmap/3 is just a wrapper for pairs_key_unmapped/3:
unmap(Key,Ps0,Ps) :-
pairs_key_unmapped(Ps0,Key,Ps).
The implementation of pairs_key_unmapped/3 is built on the predicates if_/3 and =/3 (a.k.a. equal_truth/3), as defined by #false in an answer to "Prolog union for A U B U C":
pairs_key_unmapped([],_,[]).
pairs_key_unmapped([P|Ps],K,Us) :-
P = (K0,_),
if_(K0=K, Ps=Us, (Us=[P|Us0],pairs_key_unmapped(Ps,K,Us0))).
Let's run some queries!
?- unmap(key1,[(key1,value1),(key2,value2),(key3,value3)],Ps).
Ps = [(key2,value2),(key3,value3)]. % succeeds deterministically
?- unmap(key4,[(key1,value1),(key2,value2),(key3,value3)],Ps).
Ps = [(key1,value1),(key2,value2),(key3,value3)]. % succeeds deterministically
Let's try something different... What if Key occurs twice in Ps0?
?- unmap(key1,[(key1,x),(key1,y)],Ps). % only the 1st occurrence is removed
Ps = [(key1,y)]. % succeeds deterministically
What if Ps0 is unknown, but Ps is known?
?- unmap(key4,Ps0,[(key1,value1),(key2,value2),(key3,value3)]).
Ps0 = [(key4,_A), (key1,value1),(key2,value2),(key3,value3)] ;
Ps0 = [(key1,value1),(key4,_A), (key2,value2),(key3,value3)] ;
Ps0 = [(key1,value1),(key2,value2),(key4,_A), (key3,value3)] ;
Ps0 = [(key1,value1),(key2,value2),(key3,value3) ] ;
Ps0 = [(key1,value1),(key2,value2),(key3,value3),(key4,_A) ] ;
false.
How about something a little more general?
?- unmap(Key,Ps0,[_,_]).
Ps0 = [(Key,_A),_B, _C ] ;
Ps0 = [(_A,_B), (Key,_C), _D ], dif(_A,Key) ;
Ps0 = [(_A,_B), (_C,_D) ], dif(_A,Key), dif(_C,Key) ;
Ps0 = [(_A,_B), (_C,_D), (Key,_E)], dif(_A,Key), dif(_C,Key) ;
false.
And what answers does the most general query give us?
?- unmap(Key,Ps0,Ps).
Ps0 = [], Ps = [] ;
Ps0 = [(Key,_A)|Ps] ;
Ps0 = [(_A,_B)], Ps = [(_A,_B)], dif(_A,Key) ;
Ps0 = [(_A,_B),(Key,_C)|_Z], Ps = [(_A,_B)|_Z], dif(_A,Key) ;
Ps0 = [(_A,_B),(_C,_D)], Ps = [(_A,_B),(_C,_D)], dif(_A,Key), dif(_C,Key) ...
The issue is with your base case:
unmap(X, _, X).
If your main predicate clause fails (the key isn't found), it reverts to the base case, which will instantiate your result (third argument) with only the key (first argument). Your base case should be:
unmap(_, X, X).
Which will instantiate the result (third argument) with the original list (second argument).
Note that the main clause could be simpler (this will work in GNU or SWI prolog):
unmap(K, M, R):-
select((K, _), M, M1),
unmap(K, M1, R), !.
The cut prevents backtracking to the base case if the first clause succeeds.
In SWI Prolog, the delete/3 predicate will work in your favor:
unmap(K, M, R) :-
delete(M, (K,_), R), !.
delete/3 is more strict in GNU Prolog and will not work in this case.
This isn't so much an answer to the question, but a simpler way of attacking it, without using the 'select' (or any other built-in predicates), and only using recursion.
Considering that the output list is just a list of items that didn't match the key, you need 2 main clauses, and iterate around the list. One where the key matches the head of the list, and one that doesn't.
unmap(_, [], []).
% head of the list matches key, do not add K/H to unmatched list (ie remove it)
unmap(K, [(H, _)|Tail], Unmatched) :-
H == K,
unmap(K, Tail, Unmatched).
% above rule fails, add H to unmatched list
unmap(K, [H|Tail], [H|Unmatched]) :-
unmap(K, Tail, Unmatched).
?- unmap(key1, [(key1, value1),(key2, value2),(key3, value3)], R).
R = [ (key2, value2), (key3, value3)] .
?- unmap(key4, [(key1, value1),(key2, value2),(key3, value3)], R).
R = [ (key1, value1), (key2, value2), (key3, value3)] .
So if the key doesn't exist, it just iterates around adding all list items, and so the input and output lists are identical.
I've been trying to write a predicate which would evaluate the size of a list to be even or not and this has to be done without computing the length of the list or any arithmetic operations. It's supposedly easier than computing the length but I'm having trouble thinking of how to do it without that. I'm guessing a sort of recursive technique but if anyone is able to help it would be great.
Yes, you want recursion. The base cases would be the smallest odd/even lists you can have, and then all you need is to figure out how to construct the recursive call so that it will boil down to the base case. You could start out by imagining a list of length 3 that's supposed to return true for "oddList". If it's not the base case, what's the next logical step? How does an odd list differ from an even one?
Preserve logical-purity! Simply proceed like this:
evenlength([]). % smallest list with even length is [] (length=0)
evenlength([_|Xs]) :-
oddlength(Xs).
oddlength([_|Xs]) :- % smallest list with odd length is [_] (length=1)
evenlength(Xs).
Some simple ground queries for evenlength/1 and oddlength/1:
?- evenlength([]).
true.
?- oddlength([]).
false.
?- evenlength([1]).
false.
?- oddlength([1]).
true.
?- evenlength([1,2]).
true.
?- oddlength([1,2]).
false.
?- evenlength([1,2,3]).
false.
?- oddlength([1,2,3]).
true.
Note that these predicates can not only test candidate lists, but also generate them:
?- evenlength(Xs).
Xs = []
; Xs = [_A,_B]
; Xs = [_A,_B,_C,_D]
; Xs = [_A,_B,_C,_D,_E,_F]
...
?- oddlength(Xs).
Xs = [_A]
; Xs = [_A,_B,_C]
; Xs = [_A,_B,_C,_D,_E]
; Xs = [_A,_B,_C,_D,_E,_F,_G]
...
Using meta-predicate foldl/4 and Prolog lambdas all we need to do is:
evenlength(Xs) :-
foldl(\_^E^O^(O is \E),Xs,1,1). % each item in `Xs` flips the "evenness flag"
Sample uses:
?- evenlength([]).
true.
?- evenlength([_]).
false.
?- evenlength([_,_]).
true.
?- evenlength([_,_,_]).
false.
?- evenlength([_,_,_,_]).
true.
Let's not forget about the most general query!
?- evenlength(Xs).
Xs = []
; Xs = [_A,_B]
; Xs = [_A,_B,_C,_D]
; Xs = [_A,_B,_C,_D,_E,_F]
...
I know it is too late to answer your question, but hopefully this will help:
To find list has odd length:
oddlength([_]).
oddlength([_,_|R]) :- oddlength(R),!.
To find list has even length:
evenlength([]).
evenlength([_,_|R]) :- evenlength(R),!.