2011-08-22 36 views
2

晚上好, 我有一个简单的问题,并且我警告你,我对prolog很新。 假设有三个相同大小的列表,每个只包含1s,0s或-1s。 我想验证的是,对于所有我,这三个列表中的第i个元素,只有一个非零。序言:迭代

该代码会为一个固定的我:

:- use_module(library(clpfd)). 

compat1(V1,V2,V3,I) :- 
    length(V1,G), 
    nth1(I,V1,X), 
    nth1(I,V2,Y), 
    nth1(I,V3,Z), 
    W is X*X+Y*Y+Z*Z, 
    W is 1, 
    I in 1..G. 

我怎么能说 “我为人人,compat1(V1,V2,V3,I)”? 我试图定义

compat2(V1,V2,V3,1) :- compat1(V1,V2,V3,1). 
compat2(V1,V2,V3,K) :- compat2(V1,V2,V3,J), compat1(V1,V2,V3,K), K is J+1. 

,这样我可以以K称它为我感兴趣的 但compat2不起作用=最大值:让真实的,那么,后“;”无限期地运行。

谢谢!

回答

2

一些言论:混合library(clpfd)(is)/2大多不是一个好主意。您可以使用X #= Y + 1来代替X is Y + 1,效率几乎相同(在SWI中),但享受其增加的通用性。

您感兴趣的关系与三个列表的第i个元素有关。也就是说,我们可以写:maplist(r, Xs, Ys, Zs)其中r/3是您感兴趣的关系。所以我们必须定义r(X,Y,Z)

abs(X)+abs(Y)+abs(Z) #= 1怎么样?

有了你可以把library(lambda)这一切转化为一个单行:

maplist(\X^Y^Z^(abs(X)+abs(Y)+abs(Z) #= 1), Xs, Ys, Zs). 
+1

优雅和简单。非常有用,谢谢你告诉我不要使用是/ 2。 – Martino

+1

另一个问题。我如何总结一个涉及索引的列表?例如,我怎么能总结我的表达我* A(我)? – Martino

0

你可以用一个简单的递归做到这一点。该程序只测试输入,不能用于生成解决方案。如果你需要,你必须说出事实中允许哪些数值,例如加入onlyOne(0,0,1). onlyOne(0,0,-1).

onlyOne(0,0,_). 
onlyOne(0,_,0). 
onlyOne(_,0,0). 
onlyOne([],[],[]). 
onlyOne([H1|T1],[H2|T2],[H3|T3]) :- onlyOne(H1,H2,H3), onlyOne(T1,T2,T3). 

编辑:重读我猜你需要确切地一个条目是非零的问题,而不是在最之一。在这种情况下,你需要这些规则,而不是事实:

onlyOne(0,0,X) :- X \= 0. 
onlyOne(0,X,0) :- X \= 0. 
onlyOne(X,0,0) :- X \= 0.