我将编写谓词,只有当X
出现在Y
列表L
before(L, X, Y) :-
nth1(PX, L, X),
nth1(PY, L, Y),
PX < PY.
上面,你可以看到我的解决方案。你怎么看待这件事 ?
谈到我的具体问题:
当至少有一对Y
跟随X
时,我的谓词返回true。如何定义谓词,使每个对都成立?
答案 0 :(得分:4)
您展示的解决方案适用于&#34;如果存在&#34;案例,但在某种程度上是必要的。也就是说,它有点像翻译成Prolog的C程序。势在暗示意味着您使用编程语言告诉计算机,执行哪些步骤以实现结果。
为了更具说明性或关系性,你的&#34;存在&#34;解决方案可以很好地表达为DCG:
...
(注意:您可以在Prolog中有一个名为X
的谓词,此处显示。)这描述了列表中Y
和X
的关系。它没有描述要执行的步骤,而是描述序列中Y
和X
的关系。此解决方案已显示before on SO。
遵循这种方法(我们描述Y
和X
的关系),表达所有Y
的所有before_all(X, Y) -->
{ dif(X,Y) },
any_sequence_but(Y), [X], any_sequence_but(Y), [Y], any_sequence_but(X).
any_sequence_but(_) --> [].
any_sequence_but(Y) --> [X], { dif(X,Y) }, any_sequence_but(Y).
之前的一种方式(不一定是唯一的方法) 1}}将是:
?- phrase(before_all(X,Y), [b,a,b,c,a,b,d]).
X = b,
Y = d ;
X = a,
Y = d ;
X = b,
Y = d ;
X = c,
Y = d ;
X = a,
Y = d ;
X = b,
Y = d ;
false.
?-
这产生了这样的解决方案:
{{1}}
答案 1 :(得分:0)
如果条件应该适用于所有对,则条件应该至少保持一对,而任何对的条件不应该为真。
我冒昧地将您的before/3
重命名为beforeSome/3
。
beforeSome(L, X, Y) :-
nth1(PX, L, X),
nth1(PY, L, Y),
PX < PY.
beforeAll(L, X, Y) :-
beforeSome(X,Y),
not(beforeSome(L, Y, X)).
产生了预期的结果:
?- beforeAll([1,2,3,1,4,5], 1, 4).
true.
?- beforeAll([1,2,3,1,4,5], 1, 2).
false.
请注意,使用nth1/3
会阻止它与未实例化的变量一起使用。换句话说,beforeAll([1,2,3,1,4,5], X, Y).
是false
。
beforeSome/3
的更好实现类似于
beforeSome([X|T], X, Y) :-
member(Y, T).
beforeSome([_|T], X, Y) :-
beforeSome(T, X, Y).
% no change needed, but repeated here for completeness' sake
beforeAll(L, X, Y) :-
beforeSome(X,Y),
not(beforeSome(L, Y, X)).