Prolog-查找列表的产品 [英] Prolog - finding the product of a list

查看:79
本文介绍了Prolog-查找列表的产品的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆