我发誓这不是一个功课问题。几十年来我没有上过课。曾几何时,我想出了一个可爱的分区函数递归公式:
/ 0 (k > n)
f(k, n) { 1 (k = n)
\ p(k, n-k)+p(k+1, n) (k < n)
我想在prolog中尝试代表这一点。这是我能得到的:
partition(N, N, 1) :- !. %% http://stackoverflow.com/a/9582409
partition(K, N, 0) :- K > N.
partition(K, N, A+B) :-
X is K+1,
Y is N-K,
partition(X, N, A),
partition(K, Y, B).
?- partition(1, 10, X).
给了我这个:
X = 1 + 0 + 0 + 0 + 0 + 1 +(1 + 0 + 0)+(1 + 0 + 0 + 0 +(1 + 0))+(1 + 0 + 0 + 0 + 1+(1 + 0 + 0)+(1 + 0 + 0 + 1 +(1 + 0 + 1)))+(1 + 0 + 0 + 0 + 0 +(1 + 0)+(1 + 0 + 0 + 1)+(1 + 0 + 0 + 0 +(1 + 0)+(1 + 0 + 0 +(1 + 0)))+(1 + 0 + 0 + 0 + 1 +(1 + 0 + 0)+(1 + 0 + 0 + 1 +(1 + 0 + 1))+(1 + 0 + 0 + 0 +(1 + 0)+(1 + 0 + 0 +(1 + 0) )+(1 + 0 + 0 + 1 +(1 + 0 + 1)+(1 + 0 + 0 +(1 + 0)+(1 + 0 + 1 +(1 + 0 +(1 + 1)) )))))))?
令人欣慰的是,在上面的表达中确实有42个(?)。我希望X=42.
注意问号。是的,还有更多的比赛(显然无限多)。第二个是:
X = 1 + 0 + 0 + 0 + 0 + 1 +(1 + 0 + 0)+(1 + 0 + 0 + 0 +(1 + 0))+(1 + 0 + 0 + 0 + 1+(1 + 0 + 0)+(1 + 0 + 0 + 1 +(1 + 0 + 1)))+(1 + 0 + 0 + 0 + 0 +(1 + 0)+(1 + 0 + 0 + 1)+(1 + 0 + 0 + 0 +(1 + 0)+(1 + 0 + 0 +(1 + 0)))+(1 + 0 + 0 + 0 + 1 +(1 + 0 + 0)+(1 + 0 + 0 + 1 +(1 + 0 + 1))+(1 + 0 + 0 + 0 +(1 + 0)+(1 + 0 + 0 +(1 + 0) )+(1 + 0 + 0 + 1 +(1 + 0 + 1)+(1 + 0 + 0 +(1 + 0)+(1 + 0 + 1 +(1 +(0 + 0)+(1 +1)))))))))?
答案 0 :(得分:3)
我发誓这不是一个功课问题。几十年来我没有上过课。
冷静下来,即使是家庭作业,在你做出合理努力的情况下寻求帮助也没有问题(合理的当然是主观的,但我认为问题还可以)你自己,并且更多的是你的实现存在特定问题:)。
你的方法的问题在于你 - 在众多中 - 认为Prolog将语义附加到仿函数上。 对于Prolog +
不是加分,也不是一起添加,+
只是一个符号,不评估。
然而,有一个谓词可以评估表达式树,并使用大多数人都同意的“语义”。这是is/2
谓词。所以现在您只需将其修改为:
partition(K, N, C) :- X is K+1, Y is N-K, partition(X, N, A), partition(K, Y, B), C is A+B.
是的,有更多的匹配(显然无限多)。
那是因为你的最后一个条款没有 guard 表示K < N
,换句话说,Prolog会回溯,无论K
和{ {1}}彼此相关,它总是可以选择最后一个子句(N
除外,因为你放了一个剪切(K == N
))。
您最好使用“ guard ”作为最后一个子句,否则可以在回溯时!
调用它。所以完整的代码序列会读取如下内容:
partition(N, N, 1) :- !. %% http://stackoverflow.com/a/9582409 partition(K, N, 0) :- K > N. partition(K, N, C) :- K < N, X is K+1, Y is N-K, partition(X, N, A), partition(K, Y, B), C is A+B.
请注意K < N
没有什么特别之处:它只是一个谓词:您也可以使用is/2
调用它。它只是以这种方式定义,它也可以用作中缀运算符。
使用给定的子句,查询给出:
is(C,A+B)