Сравнить равенство и вывести значение равенства - PullRequest
0 голосов
/ 09 мая 2018

Я хочу сравнить 2 значения X и C1, как вы можете видеть в коде, X - это обратное значение C, если оба значения равны, тогда следует вывести сравниваемое значение, пожалуйста, скажите мне, как это сделать. Это печатать номера палиндрома, как ... 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 голосов
/ 10 мая 2018

Описание чисел палиндрома на самом деле хорошая задача для 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, а цифры должны быть умножены на соответствующие им степени десяти и суммированы. Поскольку начальные нули исключаются 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 как начальная степень десяти и 0 как начальный накопитель для числа. Цифры умножаются на степень десяти, соответствующую их положению в числе, и затем добавляются в аккумулятор. Если список цифр пуст, аккумулятор содержит номер, соответствующий списку цифр.

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.

EDIT

Чтобы ответить на вопрос в своем комментарии, вы можете сделать это, описав отношение между такой последовательностью и ее длиной. Таким образом, у вас будет предикат с арностью два вместо арности один. Давайте дадим ему хорошее описательное имя, скажем firstN_palindromicnumbers/2. Фактическая реализация описывается предикатом с дополнительным аргументом, который содержит текущего кандидата, подлежащего проверке. Поскольку вы хотите начать последовательность с 1, это будет аргумент firstN_palindromicnumbers_ / 3 будет вызываться с:

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

Аргумент, содержащий кандидатов, будет увеличен на 1 посредством рекурсий, тогда как первый аргумент, N, будет уменьшаться каждый раз, когда кандидат оказывается действительным палиндромным числом. Таким образом, предикат в конечном итоге заканчивается N, равным 0, пустым списком и кандидатом, который нас не волнует. Это будет базовый случай. В противном случае заголовок списка - это наименьшее число палиндромов в (оставшейся части) последовательности. Вы можете повторно использовать цели number_codes/2 и maplist/3 сверху, чтобы описать список цифр, соответствующий текущему кандидату, и DCG palindrome//0, чтобы указать, что цифры должны быть палиндромом. Другие цели из предиката palindromedigits/1 не понадобятся, так как кандидаты будут 1,2,3, ..., таким образом, состоящие из (по крайней мере) одной цифры (цифр) от 0 до 9 без начальных нулей. Вы можете выразить это в Прологе так:

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] ;
.
.
.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...