比较Equality和Print the Equal值

时间:2018-05-09 19:38:29

标签: prolog

我想在代码中看到比较2个值X和C1,如果两个值相等则X是C的反转值然后它应该打印比较值请告诉我如何执行此操作。它是打印Palindrome数字,如... 1,11,22,33,44,55,66,77,88,99,101 ....

    go(N):-
        write(0),nl,
        go(0,N).
    go(_,0):- !.
    go(A,C):-
        A1 is A,
        C1 is A1 + 1,
       /* write(C1),nl,*/
        rev(C1,X),
       /* write(X),nl,*/

/* To compare the Value of X and C1 and print if compared value is true*/

        NewC is C-1,
        go(C1,NewC).

    rev(Q,E):-

        name(Q, Q1),
        reverse(Q1,E1),
        name(E,E1).

1 个答案:

答案 0 :(得分:2)

描述回文数对于CLP(FD)和DCG来说实际上是一项很好的任务。首先让我们描述一个回文数字的数字:

:- use_module(library(clpfd)).

palindromedigits(Digits) :-        % Digits are palindrome digits if 
   Digits ins 0..9,                % they are between 0 and 9
   Digits = [H|_],                 % and the first digit...
   H #\= 0,                        % ... is different from 0
   phrase(palindrome, Digits).     % and they form a palindrome

palindrome -->                     % a palindrome is
   [].                             % an empty list
palindrome -->                     % or
   [_].                            % a list with a single element
palindrome -->                     % or
   [A],                            % an element A
   palindrome,                     % followed by a palindrome
   [A].                            % followed by an element A

要测试一个数字是否为回文数,您可以将其转换为数字列表,palindromedigits/1必须为该列表保留。要生成此类数字,您可以使用length/2来描述所有可能长度的列表,palindromedigits/1必须再次为这些列表保留,并且数字必须乘以它们各自的10的幂并总结。由于palindromedigits/1排除了前导零,因此如果要将其包含在回文数中,则必须为0添加一个事实。这可能看起来像这样:

palindromenumber(0).                % 0 is a palindromenumber
palindromenumber(PN) :-             % rule for testing numbers
   number(PN),                      % succeeds if PN is a number 
   number_codes(PN,C),              % C is a list of codes corresponding to the digits
   maplist(plus(48),Digits,C),      % codes and digits are off by 48
   palindromedigits(Digits).        % Digits is a palindrome   
palindromenumber(PN) :-             % rule for generating numbers
   var(PN),                         % succeeds if PN is a variable
   length(Digits,_),                % Digits is a list of length 0,1,2,...
   palindromedigits(Digits),        % Digits is a palindrome
   digits_number_(Digits,PN,1,0),   % Digits correspond to the number PN
   label(Digits).                   % labels the list Digits with actual numbers

请注意,与数字对应的代码关闭了48,因此maplist/3的目标是关闭的,例如:

?- number_codes(123,C), maplist(plus(48),Digits,C).
C = [49, 50, 51],                                    % <- the codes
Digits = [1, 2, 3].                                  % <- the actual digits

谓词digits_number_/4非常简单。它被调用1作为10的初始幂,0作为数字的初始累加器。数字乘以对应于它们在数字中的位置的10的幂,然后加到累加器中。如果数字列表为空,则累加器保存与数字列表对应的数字。

digits_number_([],PN,_,PN).         
digits_number_([D|Ds],PN,P,Acc) :-  
   Acc1 #= Acc + D*B,               
   P10 #= P*10,                     
   digits_number_(Ds,PN,P10,Acc1).  

请注意,数字与相反顺序的功率相乘并不重要,因为它是回文数。

现在您可以查询回文数:

?- palindromenumber(PN).
PN = 0 ;
PN = 1 ;
PN = 2 ;
.
.
.
PN = 33 ;
PN = 44 ;
PN = 55 ;
.
.
.
PN = 666 ;
PN = 676 ;
PN = 686 ;
.
.
.
PN = 7667 ;
PN = 7777 ;
PN = 7887 
.
.
.

或者你可以测试一个数字是否是回文:

?- palindromenumber(121).
true ;
false.

?- palindromenumber(123).
false.

?- palindromenumber(12321).
true ;
false.

修改

要解决评论中的问题,您可以通过描述此序列与其长度之间的关系来实现。因此,您将拥有一个带有arity而不是arity的谓词。让我们给它一个很好的描述性名称,比如firstN_palindromicnumbers/2。实际的realation由一个带有附加参数的谓词描述,该附加参数保存当前要检查的候选项。由于你想用1开始序列,这将是参数firstN_palindromicnumbers_ / 3将被调用:

firstN_palindromicnumbers(N,PNs) :-
   firstN_palindromicnumbers_(N,PNs,1).       % sequence starts with 1

通过递归,持有候选者的参数将增加1,而第一个参数N将在每次候选结果变为实际回文数时减少。因此,谓词最终以N0,空列表和我们不关心的候选者结束。这将是基本情况。否则,列表的头部是(序列的其余部分)中的最小回文数。您可以重复使用上面的目标number_codes/2maplist/3来描述与当前候选人和DCG palindrome//0对应的数字列表,以声明数字必须是回文。谓词palindromedigits/1中的其他目标将不再需要,因为候选者将是1,2,3,...,因此由0到9的(至少一个)数字组成而没有前导零。你可以在Prolog中表达这样:

firstN_palindromicnumbers_(0,[],_C).          % base case
firstN_palindromicnumbers_(N1,[C0|PNs],C0) :- % case: C0 is a palindrome
   N1 #> 0,                                   % sequence is not of desired length yet
   number_codes(C0,Codes),
   maplist(plus(48),Digits,Codes),
   phrase(palindrome, Digits),                % digits form a palindrome
   N0 #= N1-1,                                % sequence of length N1-1 has to be described yet
   C1 #= C0+1,                                % C1 is the next candidate
   firstN_palindromicnumbers_(N0,PNs,C1).     % PNs is the rest of the sequence
firstN_palindromicnumbers_(N1,PNs,C0) :-      % case: C0 ain't a palindrome
   N1 #> 0,                                   % sequence is not of desired length yet
   number_codes(C0,Codes),
   maplist(plus(48),Digits,Codes),
   \+ phrase(palindrome, Digits),             % digits don't form a palindrome
   C1 #= C0+1,                                % C1 is the next candidate 
   firstN_palindromicnumbers_(N1,PNs,C1).     % PNs is the rest of the sequence

现在您可以查询谓词中给定长度的回文数字序列(请注意,使用SWI-Prolog,您可能需要点击 w 才能看到整个列表):

?- firstN_palindromicnumbers(15,PNs).
PNs = [1, 2, 3, 4, 5, 6, 7, 8, 9|...] [write]               % <- hit the w key
PNs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66] ;
false.

?- firstN_palindromicnumbers(25,PNs).
PNs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161] ;
false.

您还可以使用谓词来检查给定列表是否是第一个N回文数字的序列:

?- firstN_palindromicnumbers(N,[1,2,3,4,5]).
N = 5 ;
false.

?- firstN_palindromicnumbers(N,[0|_]).
false.

?- firstN_palindromicnumbers(N,[1,2,3,4,11]).
false.

最常见的查询也会产生预期的答案:

?- firstN_palindromicnumbers(N,PNs).
N = 0,
PNs = [] ;
N = 1,
PNs = [1] ;
N = 2,
PNs = [1, 2] ;
N = 3,
PNs = [1, 2, 3] ;
.
.
.