Prolog 序言,列表中Y元素之前的X元素

Prolog 序言,列表中Y元素之前的X元素,prolog,Prolog,我要写的谓词只有当元素X出现在列表L的Y之前时才是真的 before(L, X, Y) :- nth1(PX, L, X), nth1(PY, L, Y), PX < PY. (L,X,Y)之前的:- nth1(PX,L,X), nth1(PY,L,Y), PX

我要写的谓词只有当元素
X
出现在列表
L
Y
之前时才是真的

before(L, X, Y) :-
    nth1(PX, L, X),
    nth1(PY, L, Y),
    PX < PY.  
(L,X,Y)之前的
:-
nth1(PX,L,X),
nth1(PY,L,Y),
PX
在上面,您可以看到我的解决方案。你觉得怎么样

说到我的具体问题:

当至少有一对
Y
后跟
X
时,我的谓词返回true。如何定义谓词,使其对每一对都为真?

如果该条件对所有对都适用,则该条件应至少对一对适用,而对任何对都不适用

我冒昧地将您的
before/3
重命名为
before/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)).

请注意,您使用的
nth1/3
排除了它与未实例化变量一起使用。换句话说,
beforeal([1,2,3,1,4,5],X,Y)。
false

在某些/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)).

如果该条件应适用于所有对,则该条件应适用于至少一对,而其相反情况不应适用于任何对

我冒昧地将您的
before/3
重命名为
before/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)).

请注意,您使用的
nth1/3
排除了它与未实例化变量一起使用。换句话说,
beforeal([1,2,3,1,4,5],X,Y)。
false

在某些/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)).

您展示的解决方案适用于“如果存在”的情况,但在本质上有点必要。也就是说,它有点像翻译成Prolog的C程序。命令式意味着您正在使用编程语言告诉计算机要执行哪些步骤才能获得结果

为了更具声明性或关系性,您的“存在”解决方案可以很好地表示为DCG:

... --> [].
... --> [_], ... .

before(X, Y) --> ... , [X], ... , [Y], ... .
(注意:在Prolog中可以有一个名为
..
的谓词,如下所示。)这描述了列表中
X
Y
的关系。它不描述要执行的步骤,而是描述顺序中的
X
Y
之间的关系。这个解决方案已经展示出来了

按照这种方法(我们描述了
X
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).
这就产生了这样的解决方案:

?- 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.

?-

您展示的解决方案适用于“如果存在”的情况,但在本质上有点必要。也就是说,它有点像翻译成Prolog的C程序。命令式意味着您正在使用编程语言告诉计算机要执行哪些步骤才能获得结果

为了更具声明性或关系性,您的“存在”解决方案可以很好地表示为DCG:

... --> [].
... --> [_], ... .

before(X, Y) --> ... , [X], ... , [Y], ... .
(注意:在Prolog中可以有一个名为
..
的谓词,如下所示。)这描述了列表中
X
Y
的关系。它不描述要执行的步骤,而是描述顺序中的
X
Y
之间的关系。这个解决方案已经展示出来了

按照这种方法(我们描述了
X
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).
这就产生了这样的解决方案:

?- 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.

?-

谢谢你在帖子底部的警告。这似乎值得考虑。你能看到另一个方向吗?毕竟,
beforeal([1,2,3,1,4,5],X,Y)
X
Y
未实例化)总是
false
。PS:我的任务告诉我,只有列表总是实例化的。然而,我意识到了这一点——毕竟未实例化的
X
Y
总是返回false。您可以使用
前置([X | T],X,Y):-成员(Y,T)。前体([H | T],X,Y):-dif(H,X),前体(T,X,Y)。
用于
前体/3
,但
非/1
阻止生成。所以这也需要另一个定义。请告诉我,为了找到解决方案,如何考虑谓词?我经常遇到这样的问题:我的解决方案不是泛型的。这允许列表中不存在的元素成功,因此,例如,这成功:
beforeAll([1,2,3,4,5,6],9,8)。
@潜伏者同意。首先检查会员资格可以解决这个问题。谢谢你在帖子底部的警告。这似乎值得考虑。你能看到另一个方向吗?毕竟,
beforeal([1,2,3,1,4,5],X,Y)
X
Y
未实例化)总是
false
。PS:我的任务告诉我,只有列表总是实例化的。然而,我意识到了这一点——毕竟未实例化的
X
Y
总是返回false。您可以使用
前置([X | T],X,Y):-成员(Y,T)。前体([H | T],X,Y):-dif(H,X),前体(T,X,Y)。
用于
前体/3
,但
非/1
阻止生成。所以这也需要另一个定义。请告诉我,为了找到解决方案,如何考虑谓词?我经常遇到这样的问题:我的解决方案不是泛型的。这允许列表中不存在的元素成功,因此,例如,这成功:
beforeAll([1,2,3,4,5,6],9,8)。
@潜伏者同意。首先检查成员资格可以解决这个问题。你可能想看看这个。我认为您的解决方案存在一个问题,即您必须考虑Prolog。也就是说,你在问自己“我该告诉Prolog如何处理这些信息才能得到我想要的结果”,而不是用关系思维。那么,如何思考呢?逻辑上这不是那么容易