A problem of judge if a number contains '0' in Prolog - prolog

Actually, I am writing a code to judge whether a number contains any 0. The function name is haveZero. For example, haveZero(109) should return true and haveZero(211) should return false. This is the code I wrote but it seems that only the base case haveZero(0) and other numbers that ends with '0' can return true.

A simple solution is to use the standard number_codes/2 predicate and the de facto standard memberchk/2 predicate:
has_zero(Number) :-
number_codes(Number, Codes),
memberchk(0'0, Codes).
The 0'0 term is a standard number notation that allows us to get the code of the character following the 0' prefix.
Sample calls:
| ?- has_zero(109).
yes
| ?- has_zero(211).
no

is means assignment in prolog. Your code assign (a number mod 10) to 0, so just the number mod 10 is 0 (ends with 0) can be true.

Related

Choicepoint pruning needs a cut, but I think the compiler should be sharp enough to do it by itself

I'm doing an exercise of writing a between/3 that takes an additional step value.
This is an interesting exercise, quickly showing:
the advantage of tagged integers (i.e. use pos(X) instead of X if X is a positive integer to take advantage of pattern matching)
the magic inherent in making the predicate as deterministic as possible (do not leave a choicepoint open at the end of the sequence)
the interest in passing a "flag" array to the predicate to fine-tune behaviour (in this case, should it throw or fail if the sequence is empty?)
But also:
the less than well-thought-out format of the ISO standard exception terms (using compound terms instead of lists to ferry info ... WTF!)
the naming of the exception-throwing predicates in library(error) (why not call them throw_... instead of confusingly giving them the same name as the exception term, will people really want to call(domain_error(...))?
the fact that must_be/2 cannot take additional position information about which arg exactly caused a problem (why!)
The complete code is between_with_step.pl ... not yet fully unit tested.
Now I have set up the following predicate
between_enum(+Start,+TaggedEnd,+TaggedStep,-Value)
which emits the next value of the increasing or decreasing sequence of integers. It uses pattern matching of tagged values. In particular, the case "end value if the sequence is an integer" (as opposed to an atom denoting infinity) and "the step is positive" is given by the following subset of clauses matching the terms int(End) and pos(Step):
% ---
% Case of "positive step" pos(Step) and "integer end" int(End) (not infinite end)
% ---
% Past end of sequence. Occurs only if the sequence is empty on entry.
between_enum(Start,int(End),pos(_),_) :-
Start > End,!,fail.
% Last entry in sequence, emit "Start" as "Value" and don't allow backtracking!
% The test "Start < End" is redundant here.
between_enum(Start,int(End),pos(Step),Start) :-
Start < End, Start+Step > End, !.
% More entries exist in sequence, emit "Start" as "Value" and DO allow backtracking!
% The test "Start < End" is redundant here.
% The test "Start+Step =< End" is redundant here, being the complement of the cut-off preceding clause
between_enum(Start,int(End),pos(Step),Start) :-
Start < End, Start+Step =< End.
% Recursive alternative to the above, digging for more values!
% The test "Start < End" is redundant here.
% The test "Start+Step =< End" is redundant here
between_enum(Start,int(End),pos(Step),Value) :-
Start < End, Start+Step =< End,
NewStart is Start+Step,
%!, % NEEDED TO MAINTAIN DETERMINACY ON LAST VALUE
between_enum(NewStart,int(End),pos(Step),Value).
Now, to be fully deterministic at the end of the enumeration, the following clause needs a cut:
between_enum(Start,int(End),pos(Step),Value) :-
Start < End, Start+Step =< End,
NewStart is Start+Step,
!, % <---- HERE
between_enum(NewStart,int(End),pos(Step),Value).
Otherwise:
With cut:
?- between(10,15,1,Value).
Value = 10 ;
Value = 11 ;
Value = 12 ;
Value = 13 ;
Value = 14 ;
Value = 15. % This is the end for sure!
Without cut:
?- between(10,15,1,Value).
Value = 10 ;
Value = 11 ;
Value = 12 ;
Value = 13 ;
Value = 14 ;
Value = 15 ; % Unsure whether this is the end?
false. % Well, turns out it is the end, really!
Shouldn't the compiler be muscular enough to determine that no further matches are possible after between_enum(Start,int(End),pos(Step),Value) - this being the last one in the series tagged with
int/1 on 2nd position and
pos/1 on third position?
This SWI-Prolog 8.1.
Edit
Could be that the compiler just indexes on the first two arguments. There is a no need for a cut in
between_enum(Start,int(End),neg(Step),Value)
which is followed only by
between_enum(Start,inf,neg(Step),Value)
as well as
between_enum(Start,minf,neg(Step),Value)
And so it can bloody well distinguish inf, minf and int(_).
Your intuition about parameter order is correct and can be confirmed with a simple experiment.
first(tag1(_),_).
first(tag2(_),_).
second(_,tag1(_)).
second(_,tag2(_)).
?- first(tag1(1),2).
true.
?- second(2,tag1(1)).
true ;
false.
This is Prolog system dependent, and depends on the available automatisms for indexing or on the available directives for indexing. For example SWI-Prolog has automatic deep indexing, but some idiosyncrasies concerning automatic multi-argument indexing. So for the example from madgen:
first(tag1(_),_).
first(tag2(_),_).
second(_,tag1(_)).
second(_,tag2(_)).
I get in my system, both queries do not leave a choice point:
Jekejeke Prolog 4, Runtime Library 1.4.7
?- first(tag1(1),2).
Yes
?- second(2,tag1(1)).
Yes
On the other hand in SWI-Prolog, a choice point is left in the second query:
SWI-Prolog (threaded, 64 bits, version 8.3.17)
?- first(tag1(1),2).
true.
?- second(2,tag1(1)).
true ;
false.
This can be quite annoying, and often facade predicates need to be
used to reorder the arguments, to make them more suitable to the
SWI-Prolog specific indexing.

Simple Prolog predicate - statement is always evaluated as false

I've just started Prolog and truly wonder why the following lines, specifically the 'is' part, always produces false:
highest(L) :-
path(_,_,Z),
Z >= L,
L is Z.
highestWrap :-
highest(0).
highestWrap is called.
Thanks in advance and have a beautiful day!
Unless there is a path with length 0, this will not work, and even then, it will likely not yield what you want: it will just say true.
In Prolog variables can only be set once, that means that if L is set to 0, then it remains 0, unless you backtrack over that assignment.
Here it thus means that you call highest(0), next you instruct Prolog to call path(_, _, Z) and this can result in zero, one or more solutions. In case there are no path(_, _, Z)s, then the call will fail. But in case there are, then Z will (if I make correct assumptions about the predicate), have a numerical value, for example 7.
Now the condition Z >= L of course holds in that case (if Z is 7), so that is nog the problem. But now you specify L is Z. That thus means that you call 0 is 7. The is/2 [swi-doc] predicate aims to solve the expression of the second argument (that expression is 7 in the example, so there is not much to solve), and then aims to unify it with the term on the left side. But since 0 is not equal to 7 that fails.
If you want to obtain the highest path, you can for example make use of the aggregate [swi-doc] library:
:- use_module(library(aggregate)).
highest(L) :-
aggregate(Max(Z), path(_,_,Z), Max(L)).
You can then call it with higest(X) to unify X with the highest value for Z in a call to path(_, _, Z).

Return Integer with Prolog

I try to understand prolog right now. I want to give the input: convert(s(s(s(X))),Y) and the output should be Y = 3.
convert(s(0), 1).
convert(s(s(0)), 2).
convert(s(X),Y) :- convert(X,Y is (Y+1)).
Those are my rules right now, but only the inputs:
convert(s(0), 1). And
convert(s(s(0)), 2). work.
If my recursion would work right, I wouldn't need the rule: convert(s(s(0)), 2).
Can someone help me with that problem?
There are two problems here:
Y is Y+1, does not makes any sense in Prolog; and
note that you here actually have written a functor.
Prolog sees this as a call:
convert(X,is(Y,Y+1))
where is(Y,Y+1) is not called, but passed as a functor. In Prolog there is no clear input and output. You call predicates and through unification, you obtain results.
We can however solve the problem by using recursion: the convert/2 of 0 is of course 0:
convert(0,0).
and the convert of an s(X), is the convert of X plus one:
convert(s(X),R) :-
convert(X,Y),
R is Y+1.
Or putting these together:
convert(0,0).
convert(s(X),R) :-
convert(X,Y),
R is Y+1.
Now we can call the predicate to list all Peano numbers and the corresponding number, as well as converting a Peano number into a number. We can also validate if a Peano number is a normal number.
Unfortunately we can not use this predicate to obtain the Peano number from a given number: it will unify with the Peano number, but in a attempt to look for another Peano number, will get stuck into an infinite loop.
We can use the clpfd library to help us with this:
:- use_module(library(clpfd)).
convert(0,0).
convert(s(X),R) :-
R #> 0,
Y #= R-1,
convert(X,Y).

What does the bitwise negation operator(\) do in prolog?

I have to implement some functions, one of which is f= ~p/\~q.
I have the following :
p(a). p(b).
q(a). q(b). q(c).
I found the function as:
f(X):-p(\X);q(\X).
When I verify it ( f(X). , f(a). , f(b). , f(c). ) it always returns false.
Shouldn't it return true for c since c is not of type p?
Thank you!
(\)/1 is an evaluable functor for bitwise complement. If you use it directly in an argument, it is only an uninterpreted functor. Evaluation is only performed with (is)/2, (>)/2 and other comparison operators.
In all current Prolog implementations you get:
?- X is \ 1.
X = -2.
Fine print: An ISO conforming system is free to define the value for \. That is, it is free, whether it uses 2's complement or another representation. However, there are only systems that use 2's complement.
Your implementation of that formula seems flawed.
You are required about f : (not p) and (not q)
A restricted negation is available in Prolog, using operator (\+)/1, and conjunction (X and Y) is expressed by comma i.e. (,)/2.
Semicolon i.e. (;)/2 means or, as for instance in the following test, that shows your initial assumption about f(c) is also wrong.
?- forall(member(X,[a,b,c,d]),(f(X)->writeln(y);writeln(n))).
n
n
n
y
(of course, after f/1 has been translated correctly)

How to implement a particular division operator in Prolog?

Implement the division operator in a way that: A is 12 div 6 div 2 result is: A = 4
So I think that I have to create an infix operator belonging to the type: yfx because this operator have first to calculate 6 div 2 and then calculate 12 div result(6 div 2)
I hope to be clear in my explanation...I know that I have explained the concept in a procedural way, but I did not know how else to express the precedence of the operations to be performed on arguments...
Ok, so I think (I hope) that the yfx form of operator is correct...
The problem is that now I don't know how to describe this operator.
In a previous exercise I have defined operator in this way:
op(600,xfx,has).
/* perter has information */
has(peter, information).
As I can read on Ivan Bratko book:
The operator definitions do not specify any operation or action. In principle, no operation or data is associated with an operator.
So I think that I can't define an operator that performs calculations.
So I think that a solution of my exercise could be something like:
op(600,yfx,div).
div(X div Y, Division) :- Division is X/Y.
But don't work well and moreover I think that this is not that they asking me to implement.
div appears to be a predeclared operator, already doing integer division, then it's sufficient to change its associativity.
Here it's the default:
?- current_op(P,A,div).
P = 400,
A = yfx.
behaving
?- A is 12 div 6 div 2.
A = 1.
change as you like:
?- [user].
|: :-op(400,xfy,div).
|: % user://1 compiled 0,04 sec, 1 clauses
true.
and you'll get
?- A is 12 div 6 div 2.
A = 4.
Beware that changing predefined operators it's bad practice. But I must say that I don't know if there is any standard way to add operators to is/2 evaluation....
edit SWI-Prolog has a way to add arithmetic: you get
?- X is 12 mydiv 6 mydiv 2.
X = 4.
after
:- op(400,xfy,mydiv).
:- arithmetic_function(mydiv/2).
mydiv(A,B,C) :- C is A div B.

Resources