在编写序言程序时,写下清晰、具体的问题陈述并分解问题会很有帮助。就像是:
一个数字是回文的,如果它是一个整数,并且如果它的数字在反转时是相同的,忽略它的符号。
这将我们引向这个接口谓词,它几乎概括了问题陈述,因此:
%---------------------
% the public interface
%---------------------
palindromic_number(X) :- % A number is palindromic if
integer(X) , % - it is an integer, and
X >= 0 , % - it is greater than or equal to zero, and
reverse_digits(X,0,X) % - its decimal value is the same if you reverse its decimal digits
. % ... OR ...
palindromic_number(X) :- % it is palindromic, if
integer(X) , % - it is an integer, and
X < 0 , % - it is less than zero, and
X1 is - X , % - its absolute value
palindromic_number(X) % - is palindromic
. % Easy!
现在,我们所要做的就是弄清楚如何反转数字的数字。鉴于我们已经消除了上面的符号处理,这很容易:从右端去除数字,将它们添加到结果的左端,直到我们达到零。
prolog 中一个有用的习惯用法是有一个公共谓词,它位于一个私有工作谓词前面,该谓词通常采用一个累加器,其中最终结果是在您递归处理问题时建立的。此外,在这种情况下(以及许多其他情况),通常有一个一般情况和一个或几个特殊情况。在这里,我们终止计算的特殊情况是源值为零时。
这导致我们对“如何反转数字的数字”的定义:
% ---------------------
% The worker predicate
% ---------------------
reverse_digits(0,T,T). % once we hit zero, the accumulator has the reversed number. Unify the accumulator with the desired result.
reverse_digits(X,T,Y) :- % Otherwise...
X > 0 , % - if X > 0,
X1 is X / 10 , % - compute the next X
D is X mod 10 , % - compute the nexst digit
T1 is 10*T + D , % - scale the accumulator and add the digit
reverse_digits(X1,T1,Y) % - recurse down.
. % - easy!
当然,另一种方法是将数字转换为字符串(这是单个字符的列表),使用内置reverse/2
谓词反转该列表并将其与原始值统一。然而,我怀疑这就是你的导师想要的。