Prolog-查找列表的产品 [英] Prolog - finding the product of a list
问题描述
我是Prolog(Swi Prolog)的新手,如果这是一个愚蠢的问题,请您谅解.这也是单项作业.我被要求查找列表的产品,这就是我想出的:
I'm super new to prolog (swi prolog) so sorry if this is a dumb question. Also this is a uni assignment. I was asked to find the product of a list and this is what I came up with:
product([],1).
product([H|T], Product) :-
product( T, Product1),
Product is H * Product1.
在最长的时间内,我的基本情况如下:
For the longest I had the base case as:
product([],0).
但是,这使一切都为零.但是,在测试基本情况时
product([],Product)
,我得到一个-这是不正确的.任何解决方案的提示将不胜感激.
But that makes everything zero. However, when testing the base case of
product([],Product)
, I get one - which is incorrect. Any hints to a solution will be appreciated.
推荐答案
这不是不正确的:1是"identity element"(身份元素)的数字"相乘.例如,您可以将操作和循环抽象化,以达到以下目的:
This is not incorrect: 1 is the identity element of "numbers" under multiplication. You can for example abstract away the operation, and the loop, to have something along the lines of:
list_op_product(L, Op, P) :-
identity_element(Op, IE),
reverse(L, R), % no foldr in SWI-Prolog, at least
foldl(Op, R, IE, P).
因此,您只需要定义identity_element/2
和操作本身.因此,加法和乘法将类似于:
So you only need to define identity_element/2
and the operation itself. So, addition and multiplication would be something like:
identity_element(add, 0).
identity_element(mult, 1).
add(X, Y, R) :- R is X + Y.
mult(X, Y, R) :- R is X * Y.
然后您可以说:
?- list_op_product([2,3,4], add, Sum).
Sum = 9.
?- list_op_product([2,3,4], mult, Product).
Product = 24.
类似地,字符串连接的标识元素是空字符串.因此,如果您仅将以下子句添加到identity_element/2
:
Similarly, the identity element of string concatenation is the empty string. So, if you just add the following clause to identity_element/2
:
identity_element(atom_concat, '').
您现在可以说:
?- list_op_product([a,b,c], atom_concat, R).
R = abc.
当然,其中大多数都是不必要的,但这表明了重点.
Of course, most of this is unnecessary, but it shows the point.
关于其他答案:也许有一种比割伤更干净的方法来避免错误答案:
As for the other answer: there is maybe a cleaner way than a cut to avoid incorrect answers:
product([], 0).
product([H|T], P) :-
product_1(T, H, P).
product_1([], P, P).
product_1([H|T], H0, P) :-
product_1(T, H, P0),
P is P0 * H0.
所以现在:
?- product([2,3,5], P).
P = 30.
?- product([], P).
P = 0.
但这感觉不对.您仍然应该有一个基本案例:
But this feels wrong. You should still have a base case:
product([], 1).
product/2
的此子句仅定义您的标识元素是什么;这就是为什么最好将1留在那里而不用0代替!但是,对于非空列表,您将减少一个乘法(您将没有最后一个* 1
).这是有效且易于实现的优化.如果尝试查找完全没有标识元素的类型的产品:那么,未定义product([], X)
.您可以省略该子句,然后?- product([], X)
将失败.或者,您可能会抛出一个错误?
This clause of product/2
simply defines what your identity element is; this is why it is still better to leave the 1 there and not replace it with a 0! However, you will do one multiplication less for non-empty lists (you won't have the last * 1
). This is a valid and easy-to-make optimization. If you try to find the product of a type that does not have an identity element at all: then, product([], X)
is not defined. You can either leave out the clause, then ?- product([], X)
will fail. Or, you can maybe throw an error?
这篇关于Prolog-查找列表的产品的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!