我无法理解prolog,我必须找到X是否在列表中的Y之前。
所以我有一个带有空列表的基本案例
before(X, Y, [ ]).
现在我知道我想检查X的索引和List中的Y的索引,如果indexX < indexY
我想要成功。
有人可以解释一个简单的方法吗?
答案 0 :(得分:3)
您可以使用append/3
找到X及其后的剩余列表,然后找到Y。
before(X, Y, L):-
append(_, [X|Tail], L),
append(_, [Y|_], Tail).
答案 1 :(得分:3)
使用DCG,它看起来像这样(使用名为...
的谓词来表示符号/视觉方便性):
before(X, Y) --> ..., [X], ..., [Y], ... .
... --> [].
... --> [_], ... .
| ?- phrase(before(X, Y), [a,b,c]).
X = a
Y = b ? ;
X = a
Y = c ? ;
X = b
Y = c ? ;
(1 ms) no
如果您愿意,可以将其包装在谓词中:
before(X, Y, L) :- phrase(before(X, Y), L).
<小时/> 正如@CapelliC所指出的,如果
X
出现在Y
之前的列表中至少有一个案例,则上述谓词会成功。但是,如果定义是 X
,则会在列表中Y
之前看到,那么另一种DCG实现可能是:
before(X, Y) --> anything_but(Y), [X], ..., [Y], ... .
anything_but(_) --> [].
anything_but(Y) --> [X], { dif(X, Y) }, anything_but(Y).
... --> [].
... --> [_], ... .
结果是:
| ?- phrase(before(X,Y), [b,a,b]).
X = b
Y = b ? a
X = a
Y = b
no
答案 2 :(得分:0)
在Prolog中,列表处理在大多数情况下是在不使用索引的情况下完成的:您使用递归,并尝试将其表示为逻辑表达式。如果您不想使用内置插件,可以写下:
before(X,Y,[X|T]) :-
!,
contains(Y,T).
before(X,Y,[_|T]) :-
before(X,Y,T).
contains(Y,[Y|_]) :-
!.
contains(Y,[_|T]) :-
contains(Y,T).
代码使用定义的contains/2
谓词来检查列表L
是否包含Y
。现在before/2
谓词包含两个子句。第一个子句指定列表的第一个元素是X
,在这种情况下,我们只需要检查列表的其余部分是否包含Y
。如果列表的第一个元素不是X
,则列表会进一步移动,并且通过使用递归,我们会尝试找到存在X
的位置。
请注意,此谓词要求X
和Y
都是列表的元素。此外,可以有多个X
和Y
。因此,before(a,b,[b,a,a,b])
会成功,因为有a
和b
,a
位于b
之前。
修改强>
如果要以相反的方式使用谓词(查询时尚),则应省略剪切:
before(X,Y,[X|T]) :-
contains(Y,T).
before(X,Y,[_|T]) :-
before(X,Y,T).
contains(Y,[Y|_]).
contains(Y,[_|T]) :-
contains(Y,T).
然后你可以查询:
?- before(X,Y,[a,b,c]).
X = a,
Y = b ;
X = a,
Y = c ;
X = b,
Y = c ;
false.
答案 3 :(得分:0)
这是一个简单的解决方案,不使用任何内置谓词。
如果您以更通用的术语重新解决问题,这会有所帮助。
常见的prolog习语是一个公共谓词,它调用一个完成所有工作的worker谓词。通常,工作者谓词将携带维持状态的附加变量。在这种情况下,我们不需要维护状态,但如果我们使实际解决方案更通用,它会简化事情:而不是根据X
和Y
来定义问题,重新定义一个任意长度的列表,定义必须在目标列表中找到事物的顺序。
然后,只需要并行递归两个列表以确定是否满足优先约束。通用解决方案(适用于包含任意数量约束的列表)有3种情况:
- 约束列表为空:成功!
- 约束列表的头部与列表的头部统一 测试。这表明已经满足约束。删除两个 约束和它刚匹配的项目(正在测试的列表的头部) 然后递减。
- 最后,只需删除正在测试的列表的头部并递归。
解决方案如下所示:
x_before_y( X , Y, Zs ) :- satisfies_constraints( [X,Y] , Zs ) .
satisfies_constraints( [] , _ ) .
satisfies_constraints( [C|Cs] , [C|Xs] ) :- satisfies_constraints(Cs,Xs) .
satisfies_constraints( Cs , [_|Xs] ) :- satisfies_constraints(Cs,Xs) .
在回溯中,这将找到所有可能的解决方案。如果这是不可取的,那么第二个条款中的一个切入将消除选择点:
satisfies_constraints( [] , _ ) .
satisfies_constraints( [C|Cs] , [C|Xs] ) :- !, satisfies_constraints(Cs,Xs) .
satisfies_constraints( Cs , [_|Xs] ) :- satisfies_constraints(Cs,Xs) .
在第3条款中引入不可统一性的测试:
satisfies_constraints( [] , _ ) .
satisfies_constraints( [C|Cs] , [C|Xs] ) :- satisfies_constraints(Cs,Xs) .
satisfies_constraints( [C|Cs] , [X|Xs] ) :-
C \= X ,
satisfies_constraints([C|Cs],Xs)
.