I am in the process of learning Prolog and I'm have trouble approaching the language coming from the object-oriented background.
I am attempted to complete the following instructions:
Implement a phased queue. This is a structure consisting of two lists:
the front end and the back end, represented as queue(Front, Back). The
queue is empty iff both lists are empty. If elements are added to the
queue they are added to the back end; if they are removed they are
removed from the front end; if the front end becomes empty (and the
back end is not empty) then the back end becomes the new front end with []
as the new back end. For example, we could start with a queue like
queue([2,5,7], []), adding 8 gives us queue([2,5,7], [8]), removing two
elements gives queue([7], [8]), adding a 9 gives queue([7], [9,8]), and
removing an element gives queue([9,8], [])
I don't understand how I create and then refer to a queue structure in the .pl file, in a way that other predicates can then manipulate and transform
I have sketched out roughly what I believe I should be doing, both defined queue structure and as just a list of lists.
add_to_q(X, [[H|T]|[H2|T2]], [[H|T]|[X|[H2|T2]]).
queue(X, Y)
add_to_q(A, queue(X,Y), queue(X, [A|Y]). % gives Syntax error: Operator expected
------------------
remove_from_q( [[H | [T|T3]] | [H2|T2]], [[T|T3]] | [H2|T2]]).
queue(X, Y)
remove_from_q( queue(X,[H|T]), queue(H,T).
How do I define and work with a structure in Prolog, how would I add what would be in a OO language methods such as getHead or getTail, I have seen examples of how you would do this with just lists but I am not working with a list of lists rather a "queue" of two separate lists?
Feeling lost!
I'm have trouble approaching the language coming from a OO background.
Do yourself a favor and forget what you know about OO while learning Prolog, it will only confuse you more when learning Prolog. In others words, don't think OO concept then how do I translated that to Prolog. Think about syntactic unification as the basis of how to construct more and more complex predicates.
I don't understand how I create and then refer to a queue structure in the PL file, in a way that other predicates can then manipulate and transform.
The instructions give you the basis for the data structure, i.e.
queue(Front,Back)
and Front and Back are a list. Examples of a list
[]
[a]
[a,b]
[a|b]
To refer to the queue is easy. Since Prolog uses syntactic unification, one side of the unification is the atom you want to unify with, e.g. queue(Front,Back) and the other side of the unification is a transformation of queue(Front,Back) you can just use them in a predicate as written.
You demonstrated this already with
add_to_q(A,queue(X,Y),queue(X,[A|Y])
Note that it is missing an ending ).
add_to_q(A,queue(X,Y),queue(X,[A|Y]). % gives Syntax error: Operator expected
It is missing an ending ).
add_to_q(A,queue(X,Y),queue(X,[A|Y])).
Since the instructions give very limited examples it is hard to create many test cases to ensure the code would work in a real production system.
Here is working code based on the question.
add(Item,queue(Front,Back),queue(Front,[Item|Back])).
remove(Item,queue([Item|[]],Back),queue(Back,[])).
remove(Item,queue([Item|Front],Back),queue(Front,Back)).
:- begin_tests(funny_queue).
funny_queue_test_case_generator(add , 8 ,queue([2,5,7] ,[ ] ) ,queue([2,5,7],[8] ) ).
funny_queue_test_case_generator(remove, 2 ,queue([2,5,7] ,[ 8] ) ,queue([5,7] ,[8] ) ).
funny_queue_test_case_generator(remove, 5 ,queue([5,7] ,[ 8] ) ,queue([7] ,[8] ) ).
funny_queue_test_case_generator(add , 9 ,queue([7] ,[ 8] ) ,queue([7] ,[9,8] ) ).
funny_queue_test_case_generator(remove, 7 ,queue([7] ,[9,8] ) ,queue([9,8] ,[] ) ).
test(add,[forall(funny_queue_test_case_generator(add,Item,Funny_queue_0,Funny_queue))]) :-
add(Item,Funny_queue_0,Funny_queue_expected),
assertion( Funny_queue == Funny_queue_expected ).
test(add,[nondet,forall(funny_queue_test_case_generator(remove,Item,Funny_queue_0,Funny_queue))]) :-
remove(Item,Funny_queue_0,Funny_queue_expected),
assertion( Funny_queue == Funny_queue_expected ).
:- end_tests(funny_queue).
This is a funny queue. When the back of the queue gets moved to the front then the items are popped in reverse order. It's not really a queue.
Nevertheless, the operations are fairly straight-forward.
To start with we will represent the queue as the compound term queue(X,Y) where X and Y are lists representing the front and the back of the queue.
We need a way to obtain an empty queue:
empty(queue([],[])).
To add an item to the queue we do this:
add(A,queue(X,Y),queue(X,[A|Y])).
Now, the instructions are inconsistent. They say that two empty lists represent an empty queue and new items are always added to the back list. So how can the first list ever become empty if it starts empty and is never added to?
So we must provide a predicate that allows us to remove from an empty front list so long as the back is not empty.
remove(queue([],[A|X]),A,queue(X,[])).
That brings the the tail of the back list to the front and returns the first element of the tail to A.
Finally, if the front list is not empty then we do this:
remove(queue([A|T],X),A,queue(T,X)).
Let's test these 4 predicates.
?-
empty(Q),
add(7,Q,Q2),
add(5,Q2,Q3),
add(2,Q3,Q4),
write(Q4),nl,
remove(Q4,A,Q5),
add(3,Q5,Q6),
remove(Q6,B,Q7),
remove(Q7,C,Q8),
remove(Q8,D,Q9),
empty(Q9),
write([A,B,C,D]).
Q9 must be empty after adding 4 atoms to the queue and then removing them. [A,B,C,D] unifies to [2,5,7,3].
Q4 is the starting state described in the instructions, albeit it's queue([],[2,5,7]) as we are instructed to always add to the back list.
So this all behaves in the way we were instructed to do so.
But it's not a true queue!
If this were a true queue then the first item added should be the first item removed. The expected output would be [7,5,2,3]. To make that work we would rewrite the first remove predicate like this:
remove(queue([],Z),A,queue(X,[])) :- reverse(Z,[A|X]).
reverse(X,Y):- reverse(X,[],Y).
reverse([],A,A).
reverse([H|T],A,R) :- reverse(T,[H|A],R).
Running the code with that change gives us the expected output of a queue.
What Guy Coder said. Forget OO anything. It's all about pattern matching.
This is about all you need:
First, a means to create an empty queue:
empty( q([],[]) ).
Once you have that, enqueuing something is trivial.
It's just a matter of prepending the enqueued item to the "back" queue:
enque( X , q(F,B) , q(F, [X|B] ) ) .
Explanation:
Lists in prolog are recursive data structures. By convention, an empty list is
denoted as the atom [] (think of it as a string). Non-empty lists are written
using square bracket notation ([1], [1,2], etc). But... that's just syntactic
sugar for the data structure ./2:
[1] is shorthand for .( 1 , [] )
[1,2] is shorthand for .( 1 , .( 2 , [] ) )
...and so on.
You can appreciate the utility of the square bracket notation. If you look at
this recursive data structure, you'll notice that a list consist of a single item,
followed by another [nested] list. That single item is the head of the list, and
the nested list is its tail.
nota bene: recursivity is an important concept in prolog. Learning to think
about things in terms of recursion will help you a LOT.
The notation [H|T] is a way of decomposing a list into its head and its tail.
And that is just syntactic sugar for .(H,T). That means that it can also be used
to create lists through composition.
So our enqueue/3 predicate is using that to construct the new "back" list with X
prepended to it.
And finally, dequeueing something isn't much more complicated:
deque( q( [] , Bs ) , F , q( Fs , [] ) ) :- reverse( Bs, [F|Fs] ).
deque( q( [F|Fs] , Bs ) , F , q( Fs , Bs ) ) .
Explanation:
The first term in the predicate deals with the case of dequeuing when the "front" list
is empty. We just reverse the back list, grab its 1st element, the head (F) as the
dequeued item, and grab its tail (Fs) as the new "front" list. And we give the new
queue an empty "back" list.
And the second term in the predicate deals with the case of dequeueing when the
"front" list is not empty. Even simpler: we just grab the head of the "front"
list, unify it as the dequeued item, and construct new queue using the tail of the
old "front" list as the new "front" list, leaving the "back" list as-is.
Example
Run it at https://swish.swi-prolog.org/p/phased-queue.pl
empty( q([],[]) ).
enque( X , q(F,B) , q(F, [X|B] ) ).
deque( q( [] , Bs ) , F , q(Fs,[]) ) :- reverse( Bs, [F|Fs] ).
deque( q( [F|Fs] , Bs ) , F , q(Fs,Bs) ).
run_example :-
empty( Q0 ) , writeln( queue : Q0 ) ,
enque( 1 , Q0 , Q1 ) , writeln( enque : Q1 ) ,
enque( 2 , Q1 , Q2 ) , writeln( enque : Q2 ) ,
enque( 3 , Q2 , Q3 ) , writeln( enque : Q3 ) ,
enque( 4 , Q3 , Q4 ) , writeln( enque : Q4 ) ,
deque( Q4 , X1 , Q5 ) , writeln( deque : x(X1) : Q5 ) ,
enque( 5 , Q5 , Q6 ) , writeln( enque : Q6 ) ,
enque( 6 , Q6 , Q7 ) , writeln( enque : Q7 ) ,
deque( Q7 , X2 , Q8 ) , writeln( deque : x(X2) : Q8 ) ,
deque( Q7 , X3 , Q9 ) , writeln( deque : x(X3) : Q9 ) ,
deque( Q9 , X4 , Q10 ) , writeln( deque : x(X4) : Q10 ) ,
deque( Q10 , X5 , Q11 ) , writeln( deque : x(X5) : Q11 ) ,
deque( Q11 , X6 , Q12 ) , writeln( deque : x(X6) : Q12 ) ,
deque( Q12 , X7 , Q13 ) , writeln( deque : x(X7) : Q13 ) ,
empty( Q13 )
.
Related
This question already has answers here:
Prolog converting integer to a list of digit
(6 answers)
Closed 1 year ago.
I wrote a Prolog predicate which transforms a list of digits in a number. So, for example, if the input is the list [1, 2, 3] then the output will be the number 123. This is my code:
convertListToNum([], Col, Col).
convertListToNum([H|T], Col, R):-
Col2 is Col * 10 + H,
convertListToNum(T, Col2, R).
convertListToNumMain(L, R):-
convertListToNum(L, 0, R).
As you can see, the arguments of the predicate are L=input, R=output, since I provide the list L as input into ConvertListToNumMain and I will get as output the number in R. If I try this predicate, it works as expected: convertListToNumMain([1, 2, 3], R) will give as output R=123.
Now what I want to do is use this function by providing the output number instead of the input list. I will use L=output, R=input. So I will not provide the list L anymore, I will provide the number R and expect to receive the list as output. So what I want is to call this: convertListToNumMain(L, 123) and I expect to receive as output L=[1, 2, 3]. However, when I call this I get the error Arguments are not sufficiently instantiated. I assume it is because in the line Col2 is Col * 10 + H I try to work with the first element of the list even tough the list is not instantiated, but I am not sure. What can I do to make this work?
I want to convert a list of digits to a number and then the number back to a list of digits and I thought I could get away with this, but apparently not. The alternative is to create another complex and inefficient predicate which will at each step find the most significant digit of a number, then add it to the list, find that number without that most significant digit and then make the next call. Or at least that is my idea. That is a lot of code and (it seems to me) more inefficient. So is there any way I can use what I already have by providing the output? If not, is there a better way than my idea above to convert a number into a list of digits (recursively, of course, since I'm using Prolog)?
It's not that complicated. Or inefficient.
int_list( N , Ds ) :- nonvar(N), number_to_digits(N,Ds).
int_list( N , Ds ) :- nonvar(Ds), digits_to_number(Ds,0,N).
digits_to_number( [] , N , N ) .
digits_to_number( [D|Ds] , T , N ) :-
T1 is 10 * T + D ,
digits_to_number(Ds,T1,N).
number_to_digits( 0 , [0] ).
number_to_digits( N , Ds ) :-
N > 0,
digits(N, [], Ds).
digits( N , T , Ds ) :-
N > 0,
D is N mod 10,
N1 is N div 10,
digits(N1,[D|T],Ds).
digits( 0 , Ds , Ds ) .
But it might be easier to use built-in predicate number_codes/2:
int_digits( N , Ds ) :- nonvar(Ds) , codes_digits(Cs,Ds) , number_codes(N,Cs) .
int_digits( N , Ds ) :- nonvar(N) , number_codes(N,Cs) , codes_digits(Cs,Ds) .
codes_digits( [] , [] ) .
codes_digits( [C|Cs] , [D|Ds] ) :- code_digit(C,D), codes_digits(Cs,Ds).
code_digit(C,D) :- nonvar(C), D is C-48.
code_digit(C,D) :- nonvar(D), C is D+48.
Each of the 7 different letters stands for a different digit. The aim is to find a substitution of digits for the letters such that the resulting sum is arithmetically correct. The solution should then produce all of the combinations of the digits that satisfy the addition problem above. Putting in a query such as crypto(P,I,N,G,O,F,U) should return your solution.
The cryptarithmetic puzzle goes like this:
P I N G
P O N G
+ F U N
---------
I G N I P
Use clpfd! Based on my previous answer to a very similar question, we run the following query:
?- Eq = ([P,I,N,G] + [P,O,N,G] + [F,U,N] #= [I,G,N,I,P]),
crypt_arith_(Eq,Zs),
labeling([],Zs).
Eq = ([7,1,9,4] + [7,0,9,4] + [6,2,9] #= [1,4,9,1,7]), Zs = [7,1,9,4,0,6,2]
; Eq = ([8,1,4,7] + [8,3,4,7] + [9,2,4] #= [1,7,4,1,8]), Zs = [8,1,4,7,3,9,2]
; Eq = ([8,1,4,7] + [8,9,4,7] + [3,2,4] #= [1,7,4,1,8]), Zs = [8,1,4,7,9,3,2]
; false.
Assuming this is a simple substitution cipher we're talking about (and just for fun), I'll take a stab at it. One should note that this is completely untested.
I'm going to set this up in a generic way, so you can say something like:
substitution_cipher( CipherExpr , CipherResult , Expr , Result , Key ).
We'll make the rule that the enciphered stuff is represented by atoms, so you can say something like this:
substitution_cipher( ping + pong + fun , ignip , Expr , Sum , Key ) .
And get the results you'd expect.
So...
First, you need the set (discrete, unique) of characters found in the cipher text:
character_set( Expr , Charset ) :-
setof( C , A^Cs^( atoms_in_expression( Expr , A ) , atom_chars(A,Cs) , member(C,Cs) ) , Charset ) .
atom_in_expression( Expr , Value ) :- atom(Expr) .
atom_in_expression( Expr , Value ) :-
Expr =.. [ _ , Left , Right ] ,
(
values( Left , Value )
;
values( Right, Value
) .
The above walks the parse tree of an expression like a * b + c * d, finding each of the leaf nodes (atoms), deconstructing them into the characters that comprise them. setof/3 ensures that the resulting list is sorted and unique.
Once you have that, you need a way of generating all the possible keys (key == mapping between a character and a digit). We want to be able to say something like
generate_key( [a,b,c] , Key )
and get back
Key = [a:1,b:2,c:3]
etc.
So:
generate_key( Charset , Key ) :-
generate_key( Charset , [] , Key ) .
generate_key( [] , Key , Key ) . % when we've exhausted the character set, we're done.
generate_key( [C|Cs] , Acc , Key ) :- % otherwise...for each character
digit(D) , % find a digit
\+ member( _:D , Acc ) , % that hasn't yet been used
generate_key( Cs , [C:D|Acc] , Key ) % map it to the character and recurse down.
.
digit(D) :- between(0,9,X) , atom_number(D,X).
Then you need a way to decode a cipher expression like
ping + pong + fun
and [try to] turn it back into proper numbers. This isn't much different than walking the parse tree and enumerating the leaf node atoms, but here we need to get them back into numeric form.
If the expression is an atom, we
decompose it into its constituent characters,
using our key, map each character to its corresponding digit,
then we turn that list of digits back into a number
decode( Key , CipherExpr , PlainExpr ) :-
atom(CipherExpression) ,
atom_chars(CipherExpression,Cs) ,
findall( D , ( member(C,Cs), member(C:D,Key) -> true ; D=C ) , Ds ) ,
number_chars( PlainExpr , Ds )
.
The general case is easy. An infix expression like ping + pong is really the prolog term +(ping,pong). We:
Decompose a infix term like ping + pong into an operator (+) and its left and right sub-expressions.
Then we recursively decode the left and right sub-expressions
Finally, we reassemble the [decoded] expression.
decode( Key , CipherExpr , PlainExpr ) :-
CipherExpr =.. [Op,L,R] ,
decode(L,L1) ,
decode(R,R1) ,
PlainExpr =.. [Op,L1,R1]
.
Then you can put it all together:
substitition_cipher( CipherExpr , CipherResult , PlainExpr , PlainResult , Key ) :-
character_set( CipherExpr = CipherResult , Charset ) ,
generate_key( Charset, Key ) ,
decode( Key , CipherExpr , PlainExpr ) ,
decode( Key , CipherResult , PlainResult ) ,
PlainResult =:= PlainExpr
.
This question already has an answer here:
Prolog map procedure that applies predicate to list elements
(1 answer)
Closed 8 years ago.
I have searched Prolog Operator expected error questions at stack overflow, however I can't identify the error I am getting :
4:26: Syntax error: Operator expected
% 3.pl compiled 0.00 sec, 3 clauses
The code is simple:
inc(N,R) :-
R is N + 1. % Simple code to increment a number.
mapcar( F , [] , [] ). % Base case
mapcar( F , [H|T] ,[RH|RT] ) :- % Increment head and put it in Result Head and Recurse for Tail
F(H,RH),
mapcar(F,T,RT).
This is really a duplicate of this question: Prolog map procedure that applies predicate to list elements
But I'll bite. You cansimply say, as was suggested:
map( _ , [] , [] ) .
map( G , [X|Xs] , [Y|Ys] ) :-
call(G,X,Y) ,
map(G,Xs,Ys) .
I have a list of terms,
[g(_G543),g(_G548),g(_G553),g(_G558),g(_G558),g(_G553),g(_G548),g(_G543)]
How can I make it to
[_G543,_G548,_G553,_G558,_G558,_G553,_G548,_G543]
only left the variables.
I was trying
replace([],[]).
replace([g(X)|T1],[X|T2]):-
replace(T1,T2).
but it just returned a false, what should I do? Thanks
If your list looks like your example
[ g(A) , g(B) , g(C) , g(A) ... ]
something like this ought to do you:
extract_vars( [] , [] ) . % if the source list is exhausted, we're done
extract_vars( [g(V)|Xs] , [V|Vs] ) :- % otherwise...
var(V) , % - ensure we've got a var
! , % - eliminate the choice point
extract_vars( Xs , Vs ) % - recurse down
. %
extract_vars( [_|Xs] , Vs ) :- % anything else, we chuck
extract_vars( Xs , Vs ) %
. % Easy!
You could probably use findall\3, too:
extract_vars( Xs , Vs ) :-
findall( V , (member(g(V),Xs),var(V)) , Vs )
.
The underscore names eg. _G553 have no real relevance, so there's no need to maintain the exact names ?
In which case, assuming all list items are all g(..), there is no need to recurse through them.. just create a new list with the same length as the input list, but without the 'g' prefix:
X=[g(_G543),g(_G548),g(_G553),g(_G558),g(_G558),g(_G553),g(_G548),g(_G543)], length(X, Len), length(Y,Len).
X = [g(_G543), g(_G548), g(_G553), g(_G558), g(_G558), g(_G553), g(_G548), g(_G543)],
Len = 8,
Y = [_G3808, _G3811, _G3814, _G3817, _G3820, _G3823, _G3826, _G3829].
Here, length/2 is used to create a list of 'Len' items.
Hello I have to solve some prolog problems with lists but i can't figure it out how these work.
I have to add "1" after every even element in a list, and to make the difference of 2 lists.
I know this seems easy, in other language like java or c# i would make it very easy, but prolog it's giving me headaches.
Please help me :|
Edited to note the clarified problem statement ("even item" meaning the item's value is even (rather than the item's ordinal position within the list):
insert_one_after_even_items( [] , [] ). % if the source list is exhaused, we're done.
insert_one_after_even_items( [X|Xs] , [X,1|Ys] ) :- % otherwise,
0 is X mod 2 , % - if the number is even, prepend it and a 1 to the result list, and
insert_one_after_even_items( Xs , Ys ) % - recurse down.
. %
insert_one_after_even_items( [X|Xs] , [X|Ys] ) :- % otherwise,
1 is X mod 2 , % - if the number is odd, prepend it to the result list, and
insert_one_after_even_items( Xs , Ys ) % - recurse down.
. % Easy!
For your second problem, producing the difference between two lists, are you talking about set differences? If so, given two sets A and B, are you talking about the relative difference (all elements of A that do not exist in B), or the absolute difference (all elements of either A or B that do not exist in both sets)?
To solve the relative set difference problem (Find all members of A that do not also exist in B), you can use the built-in member/2 predicate:
relative_difference( [] , _ , [] ) . % if the source list is exhausted, we're done
relative_difference( [A|As] , Bs , R ) :- % if the source list is non-empty, and
member(A,Bs) , % - the current A is an element of B,
! , % - we insert a deterministic cut (no backtracking)
relative_difference( As , Bs , R ) % - and recurse down, discarding the current A
. %
relative_difference( [A|As] , Bs , [A|R] ) :- % if the source list is non-empty (and A is not an element of B due to the cut inserted earlier)
relative_difference( As , Bs , R ) % we simply add A to the result list and recurse down.
.
One thing you will note here: we are building the result list in all of these examples is built from a variable. The tail of the list is unbound (and passed as the new result to the next recursive call, where it either become a new list node or, at the very end, the empty list.
This has the effect of
building the list in order (rather than in reverse order).
if the result was bound on the initial call, unification against the expected result occurs item by item as the recursion proceeds, which means
execution is short-circuited when the first unification failure occurs.
If your prolog implementation doesn't have member/2 as a built in, it's easy enough to implement. Something like this ought to do it:
member(X,[X|T]) :- ! . % A hit! cut and succeed.
member(X,[_|T]) :- member(X,T) . % ... and a miss. Just recurse down on the tail.