Simple Arithmetic in prolog - prolog

I am trying to write a program that gives a list and back a newer list that have even numbers in the first list, as below:
evennom([1,3,2,4,3,2,1,2],out)
out = [2,4,2,2]
My Code is as below:
evennom([],[]).
evennom(H1|T1],[H2|T2):- H2 is H1 mod 2.

You are close - there needs to be something that removes the first element when the mod 2 operation fails. Also, your "copy" rule was not entirely correct.
Try this:
evennom([], []).
evennom([H|T1], [H|T2]) :- H rem 2 =:= 0, !, evennom(T1, T2).
evennom([_|T1], T2) :- evennom(T1, T2).

Prolog does the recursion for you..
evennom(ListIn, ListOut) :-
findall(Even, (nth0(_, ListIn, Even), 0 is (Even mod 2)), ListOut).

Related

Variables appearing in the wrong order

So, I am doing a Prolog question and am having issues with how it runs. the question asks for me to "Write a predicate myencode/2 that takes the uncompressed list as a first parameter and returns the compressed list as shown as the second parameter". Which I have done, the only problem is it is printing out as number first, then letter. eg (2,'a'0, instead of ('a',2).
Provided below is my code, any advice on where i have gone wrong would be greatly appreciated!
pack([],[]).
pack([X|Xs],[Z|Zs]) :- transfer(X,Xs,Ys,Z), pack(Ys,Zs).
transfer(X,[],[],[X]).
transfer(X,[Y|Ys],[Y|Ys],[X]) :- X \= Y.
transfer(X,[X|Xs],Ys,[X|Zs]) :- transfer(X,Xs,Ys,Zs).
myencode(L1,L2) :- pack(L1,L), transform(L,L2).
myencode([X],X):-X=[].
myencode_modified(L1,L2) :- encode(L1,L), strip(L,L2).
transform([],[]).
transform([[X|Xs]|Ys],[[N,X]|Zs]) :- length([X|Xs],N), transform(Ys,Zs).
strip([],[]).
strip([[1,X]|Ys],[X|Zs]) :- strip(Ys,Zs).
strip([[N,X]|Ys],[[N,X]|Zs]) :- N > 1, strip(Ys,Zs).
Isn't it just
strip([[N,X]|Ys],[[N,X]|Zs]) :- N > 1, strip(Ys,Zs).
which has to be
strip([[N,X]|Ys],[[X,N]|Zs]) :- N > 1, strip(Ys,Zs).
?

Why doesn't prolog stop on cut?

I would like to get this result:
?- numberMatrixLines(1,[[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1]],X).
X = [machinePenalty(1,[1,1,1,1,1,1,1,1]),
machinePenalty(2 [1,1,1,1,1,1,1,1]),
machinePenalty(3,[1,1,1,1,1,1,1,1])]
I try the following code:
numberMatrixLines(X,[],ResultMatrix):-
writeln('should end here'),
reverse(ResultMatrix,ResultMatrixTemp),
initWith(ResultMatrixTemp,ResultMatrix),
!.
numberMatrixLines(X,[H|T],ResultMatrix):-
append_in_front(machinePenalty(X,H),ResultMatrix,ResultMatrixTemp),
writeln(ResultMatrixTemp),
incr(X,X1),
numberMatrixLines(X1,T,ResultMatrixTemp).
incr(X, X1) :-
X1 is X+1.
append_in_front(X,[],[X]).
append_in_front(X,L1,[X|L1]).
The result is correct when numberMatrixLines(X,[],ResultMatrix) is reached. HOWEVER, the predicate won't stop there and return X , as it's supposed to.
What can be done to make it stop in that line?
A straight-forward solution would be (I moved the input list to the first argument to take advantage of Prolog first-argument indexing to avoid spurious choice-points and the need of cuts):
% number_matrix_lines(+list, +integer, -list)
number_matrix_lines([], _, []).
number_matrix_lines([Line| Lines], I, [machine_penalty(I,Line)| NumberLines]) :-
J is I + 1,
number_matrix_lines(Lines, J, NumberLines).
Sample call:
| ?- number_matrix_lines([[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1]], 1, NumberLines).
NumberLines = [machine_penalty(1,[1,1,1,1,1,1,1,1]), machine_penalty(2,[1,1,1,1,1,1,1,1]), machine_penalty(3,[1,1,1,1,1,1,1,1])]
yes
P.S. Note that Prolog coding guidelines advise using underscores in predicate names instead of CamelCase.

How to parsing list in prolog until not fail

I am trying to parse a list, for example:
[1,3,3,2,2,7,2,9]
Let's say I have the following code, where isTwo will print No and fail if it is anything other than two. I WANT it to fail if it is anything other than two. If it is a two, it will print Yes and succeed.
isTwo(2) :-
write('Yes'), !.
isTwo(_) :-
write('No'), fail.
My issue is that I have something along the lines of an iterator defined, and I want to parse an entire list to find the first success.
iter([]).
iter([Head|Tail]) :-
isTwo(Head),
iter(Tail).
This works fine but will stop parsing the rest of the list as soon as failure is found. If we go back to the original list, [1,3,3,2,2,7,2,9], we get false as our output.
My question here is: how can I continue to parse in prolog while still ensuring that isTwo(_) (where it is not equal to two) will still fail, so that I can get an output of something such as NoNoNoYesYesNoYesNo in this case. Preferably without using an if-then-else clause.
This may help:
expected output: NoNoNoYesYesNoYesNo
observed output: No
Well an easy solution would be to use a second variable in iter that will help you understand if an number different than 2 is found:
isTwo(2, X, X) :-
write('Yes').
isTwo(_, _, 0) :-
write('No').
iter([], 0):- fail,!.
iter([], 1).
iter([Head|Tail], X) :-
isTwo(Head, X, Y),
iter(Tail, Y).
iter(L) :- iter(L, 1).
If you want a more concise solution, using maplist/2 you can do something like:
isTwo(2) :- write('Yes'), !.
isTwo(_):- write('No').
test(L):-
maplist(isTwo,L).
?- test([1,3,3,2,2,7,2,9]).
NoNoNoYesYesNoYesNo
true
test/1 is not mandatory, i've added it only for sake of clarity...
The other answers are both fine but the haphazard mixing in of side effects makes me a bit nervous. Also, you have a problem if the list you are "parsing" has a free variable (it will become 2 silently).
Why not like this:
is_two(X) :- X == 2, !, format("Yes").
is_two(X) :- X \== 2, !, format("No").
and then:
?- forall(member(X, [1,3,3,2,2,7,2,9]), is_two(X)).
NoNoNoYesYesNoYesNo
true.
?- forall(member(X, [Y, 2, Z]), is_two(X)).
NoYesNo
true.
Use == and \== to compare without unifying. Use forall and member to make it clear that you are doing it for the side effect. Traversing a list (or using maplist) is a bit deceiving.
forall is just a clearer way to do a failure-driven loop using negation instead of cuts and fails. The query above is identical to:
?- \+ ( member(X, [1,3,3,2,2,7,2,9]), \+ is_two(X) ).

Prolog - count occurrence of number

I want to write predicate which can count all encountered number:
count(1, [1,0,0,1,0], X).
X = 2.
I tried to write it like:
count(_, [], 0).
count(Num, [H|T], X) :- count(Num, T, X1), Num = H, X is X1 + 1.
Why doesn't work it?
Why doesn't work it?
Prolog is a programming language that often can answer such question directly. Look how I tried out your definition starting with your failing query:
?- count(1, [1,0,0,1,0], X).
false.
?- count(1, Xs, X).
Xs = [], X = 0
; Xs = [1], X = 1
; Xs = [1,1], X = 2
; Xs = [1,1,1], X = 3
; ... .
?- Xs = [_,_,_], count(1, Xs, X).
Xs = [1,1,1], X = 3.
So first I realized that the query does not work at all, then I generalized the query. I replaced the big list by a variable Xs and said: Prolog, fill in the blanks for me! And Prolog did this and reveals us precisely the cases when it will succeed.
In fact, it only succeeds with lists of 1s only. That is odd. Your definition is too restricted - it correctly counts the 1s in lists where there are only ones, but all other lists are rejected. #coder showed you how to extend your definition.
Here is another one using library(reif) for
SICStus|SWI. Alternatively, see tfilter/3.
count(X, Xs, N) :-
tfilter(=(X), Xs, Ys),
length(Ys, N).
A definition more in the style of the other definitions:
count(_, [], 0).
count(E, [X|Xs], N0) :-
if_(E = X, C = 1, C = 0),
count(E, Xs, N1),
N0 is N1+C.
And now for some more general uses:
How does a four element list look like that has 3 times a 1 in it?
?- length(L, 4), count(1, L, 3).
L = [1,1,1,_A], dif(1,_A)
; L = [1,1,_A,1], dif(1,_A)
; L = [1,_A,1,1], dif(1,_A)
; L = [_A,1,1,1], dif(1,_A)
; false.
So the remaining element must be something different from 1.
That's the fine generality Prolog offers us.
The problem is that as stated by #lurker if condition (or better unification) fails then the predicate will fail. You could make another clause for this purpose, using dif/2 which is pure and defined in the iso:
count(_, [], 0).
count(Num, [H|T], X) :- dif(Num,H), count(Num, T, X).
count(Num, [H|T], X) :- Num = H, count(Num, T, X1), X is X1 + 1.
The above is not the most efficient solution since it leaves many choice points but it is a quick and correct solution.
You simply let the predicate fail at the unification Num = X. Basically, it's like you don't accept terms which are different from the only one you are counting.
I propose to you this simple solution which uses tail recursion and scans the list in linear time. Despite the length, it's very efficient and elegant, it exploits declarative programming techniques and the backtracking of the Prolog engine.
count(C, L, R) :-
count(C, L, 0, R).
count(_, [], Acc, Acc).
count(C, [C|Xr], Acc, R) :-
IncAcc is Acc + 1,
count(C, Xr, IncAcc, R).
count(C, [X|Xr], Acc, R) :-
dif(X, C),
count(C, Xr, Acc, R).
count/3 is the launcher predicate. It takes the term to count, the list and gives to you the result value.
The first count/4 is the basic case of the recursion.
The second count/4 is executed when the head of the list is unified with the term you are looking for.
The third count/4 is reached upon backtracking: If the term doesn’t match, the unification fails, you won't need to increment the accumulator.
Acc allows you to scan the entire list propagating the partial result of the recursive processing. At the end you simply have to return it.
I solved it myself:
count(_, [], 0).
count(Num, [H|T], X) :- Num \= H, count(Num, T, X).
count(Num, [H|T], X) :- Num = H, count(Num, T, X1), X is X1 + 1.
I have decided to add my solution to the list here.
Other solutions here use either explicit unification/failure to unify, or libraries/other functions, but mine uses cuts and implicit unification instead. Note my solution is similar to Ilario's solution but simplifies this using cuts.
count(_, [], 0) :- !.
count(Value, [Value|Tail],Occurrences) :- !,
count(Value,Tail,TailOcc),
Occurrences is TailOcc+1.
count(Value, [_|Tail], Occurrences) :- count(Value,Tail,Occurrences).
How does this work? And how did you code it?
It is often useful to equate solving a problem like this to solving a proof by induction, with a base case, and then a inductive step which shows how to reduce the problem down.
Line 1 - base case
Line 1 (count(_, [], 0) :- !.) handles the "base case".
As we are working on a list, and have to look at each element, the simplest case is zero elements ([]). Therefore, we want a list with zero elements to have no instances of the Value we are looking for.
Note I have replaced Value in the final code with _ - this is because we do not care what value we are looking for if there are no values in the list anyway! Therefore, to avoid a singleton variable we negate it here.
I also added a ! (a cut) after this - as there is only one correct value for the number of occurrences we do not want Prolog to backtrack and fail - therefore we tell Prolog we found the correct value by adding this cut.
Lines 2/3 - inductive step
Lines 2 and 3 handle the "inductive step". This should handle if we have one or more elements in the list we are given. In Prolog we can only directly look at the head of the list, therefore let us look at one element at a time. Therefore, we have two cases - either the value at the head of the list is the Value we are looking for, or it is not.
Line 2
Line 2 (count(Value, [Value|Tail],Occurrences) :- !, count(Value,Tail,TailOcc), Occurrences is TailOcc+1.) handles if the head of our list and the value we are looking for match. Therefore, we simply use the same variable name so Prolog will unify them.
A cut is used as the first step in our solution (which makes each case mutually exclusive, and makes our solution last-call-optimised, by telling Prolog not to try any other rules).
Then, we find out how many instances of our term there are in the rest of the list (call it TailOcc). We don't know how many terms there are in the list we have at the moment, but we know it is one more than there are in the rest of the list (as we have a match).
Once we know how many instances there are in the rest of the list (call this Tail), we can take this value and add 1 to it, then return this as the last value in our count function (call this Occurences).
Line 3
Line 3 (count(Value, [_|Tail], Occurrences) :- count(Value,Tail,Occurrences).) handles if the head of our list and the value we are looking for do not match.
As we used a cut in line 2, this line will only be tried if line 2 fails (i.e. there is no match).
We simply take the number of instances in the rest of the list (the tail) and return this same value without editing it.

PROLOG [hand computation]

I am trying to practice hand computations in prolog could you please explain to me and demonstrate a hand computation of this certain question so I can gain more of an understanding.
In a Prolog project involving text processing (not discussed here further) a predicate duplicate/2 has been implemented for duplicating every entry of a list.
Below is an example of what duplicate/2 does:
?- duplicate([w,o,r,d], D).
D = [w,w,o,o,r,r,d,d] .
?- duplicate([], D).
D = [].
below shows the definition of duplicate/2 . Write down hand computations for duplicate/2
duplicate(L, D) :- duplicate(L,[], D). % clause 0
duplicate([], Acc, D) :- reverse(Acc, D). % clause 1
duplicate([H|T], Acc, D) :- duplicate(T, [H, H|Acc], D). % clause 2
(involving the auxiliary predicate duplicate/3 ) such that each of the three
clauses (numbered 0, 1, 2), is performed in the hand computations.
If you allow the computer to help you in hand computation there are two classical approaches to do that:
1) Use a debugger: Most of the Prolog debuggers use the Byrd box model, means it only shows you a selected goal in the process of a resolution proof. Here is a run of a smaller query for a simpler program. Usually the debugger can be switched on by trace:
?- [user].
duplicate([], []).
duplicate([X|Y], [X,X|Z]) :- duplicate(Y,Z).
^D
Yes
?- duplicate([w,o],X).
X = [w,w,o,o]
?- trace.
Yes
?- duplicate([w,o],X).
0 Call duplicate([w,o], X) ?
1 Call duplicate([o], _C) ?
2 Call duplicate([], _F) ?
2 Exit duplicate([], []) ?
1 Exit duplicate([o], [o,o]) ?
0 Exit duplicate([w,o], [w,w,o,o]) ?
X = [w,w,o,o] ;
0 Redo duplicate([w,o], [w,w,o,o]) ?
1 Redo duplicate([o], [o,o]) ?
2 Redo duplicate([], []) ?
2 Fail duplicate([], _F) ?
1 Fail duplicate([o], _C) ?
0 Fail duplicate([w,o], X) ?
No
2) Write a meta interpreter: You can write meta interpreters that deliver a trace, which can be inspected after a run and which give a certificate of the proof the Prolog system found:
This is the normal vanilla interpreter:
solve(true) :- !.
solve((A,B)) :- !, solve(A), solve(B).
solve(A) :- rule(A,B), solve(B).
Here is an interpreter that gives a trace of the applied
clauses, its implemented in DCG:
solve(true) --> [].
solve((A,B)) --> !, solve(A), solve(B).
solve(A) --> {rule(A,B)}, [(A :- B)], solve(B).
Here is an example run for the simplified duplicate query and program again:
rule(duplicate([], []), true).
rule(duplicate([X|Y], [X,X|Z]), duplicate(Y,Z)).
?- solve(duplicate([w,o],X),L,[]).
X = [w,w,o,o],
L = [(duplicate([w,o],[w,w,o,o]) :- duplicate([o],[o,o])),
(duplicate([o],[o,o]) :- duplicate([],[])),
(duplicate([],[]) :- true)]
Bye
Well let's go for a reduced version of your example query duplicate([w], D).
. There's only one rule head, which takes two arguments: the one of clause 0, with L=[w] and D1=D.(1) The body tells us, we should derive duplicate([w],[],D) instead. The head of clause 1 does not match, because [] and [w] cannot be unified. This leaves clause 2: [w] = [H|T] unifies with H=w and T=[] (2), Acc = [] and D2=D. Now our new goal is duplicate([], [w,w], D), which only matches against clause 1 (3). Our goal there is reverse([w,w],D), which is the builtin reverse/2 predicate. It is true if D unifies with the reverse list of [w,w], therefore D=[w,w]. Now we don't have any goals to derive and have found a full derivation. Since we always renamed the rule's variables, the D is still the one from our original query, meaning that D = [w,w] is a correct answer substitution for the query.
I admit I was a bit lazy, with only one duplicated letter, the reversal of the accumulator Acc seems a little pointless. To see why it is necessary, you can try the same derivation for duplicate([x,y],D), where the accumulator should be [y,y,x,x] since the elements are always prepended.
Another interesting exercise is also duplicate(X,[w,w]) and to check why duplicate(X,[w]) fails (Hint: look at the unification problem [w] = [H,H|Acc] ). What's also not contained so far is backtracking: in the case of the query duplicate(X, Y), your goal matches multiple heads and you get more than one solution (actually an infinite number of them).
Have fun playing around!
(1) A rule is true independent of how exactly its variables are named. When we have two variables of the same name D from different rules, we need to rename the D in one of the rules to something else, say D1.
(2) You can check this on the prompt by entering the unification as a query:
1 ?- [w] = [H|T].
H = w,
T = [].
(3) The reason is that the list [H|T] has at least one element, whereas [] doesn't have one. You can again check this on the prompt:
2 ?- [] = [H|T].
false.
duplicate(L, D) :- duplicate(L,[], D). % clause 0
duplicate([], Acc, D) :- reverse(Acc, D). % clause 1
duplicate([H|T], Acc, D) :- duplicate(T, [H, H|Acc], D). % clause 2
quick hand computation below for my understanding please correct me if im wrong and tell me if i am correct because i am new to prolog.
duplicate[w,o,r,d], D) clause 0 --> duplicate ([w,o,r,d],[].D).
clause 2 --> duplicate[w,o,r,d],Acc,D) --> clause 2 duplicate([o,r,d],[w,w],[],D),
i could keep going through clause 2 to keep duplicating the head of the list , i can do this till the list is empty []. then i can move to clause 1.
which i can then put my list in the accumulator then reverse it to produce [d,d,r,r,o,o,w,w]
below is the hand computation of clause 1.
clause 1 duplicate[w,w,o,o,r,r,d,d],D) ---> clause 1 reverse([w,w,o,o,r,r,d,d],D).
D = [d,d,r,r,o,o,w,w]

Resources