PROLOG列表筛选器谓词不为true或false

PROLOG列表筛选器谓词不为true或false,prolog,Prolog,我试图创建一个谓词,它接受两个向量/列表,并使用第一个作为过滤器。例如: ?- L1=[0,3,0,5,0,0,0,0],L2=[1,2,3,4,5,6,7,8],filter(L1,L2,1). L1 = [0, 3, 0, 5, 0, 0, 0, 0], L2 = [1, 2, 3, 4, 5, 6, 7, 8] . 这就是我得到的,但我希望true或false如果L2将3作为第二个元素,5作为第四个元素,等等。忽略0s,这就是“过滤”条件。 我从输入中了解到,L1和L2的长度

我试图创建一个谓词,它接受两个向量/列表,并使用第一个作为过滤器。例如:

?- L1=[0,3,0,5,0,0,0,0],L2=[1,2,3,4,5,6,7,8],filter(L1,L2,1).
   L1 = [0, 3, 0, 5, 0, 0, 0, 0],
   L2 = [1, 2, 3, 4, 5, 6, 7, 8] .
这就是我得到的,但我希望
true
false
如果L2将
3
作为第二个元素,
5
作为第四个元素,等等。忽略
0
s,这就是“过滤”条件。 我从输入中了解到,L1和L2的长度始终为8,只有L1具有
0
s

我的代码是:

filter(_,_,9).
filter([Y|T],V2,Row):-
    Y=:=0,
    NewRow is Row + 1,
    filter([Y|T],V2,NewRow).

filter([Y|T],V2,Row):-
    Y=\=0,
    nth(Row,[Y|T],X1),
    nth(Row,V2,X2),
    X1=:=X2,
    NewRow is Row + 1,
    filter([Y|T],V2,NewRow).


nth(1,[X|_],X).  
nth(N,[_|T],R):- M is N-1, nth(M,T,R).
我知道有更好的方法来实现这个函数,例如比较第一个元素和第二个元素的第n个元素,并用递归删除第一个元素的头,但我只想知道为什么我没有得到
true
false
,或任何“return”值

有人能帮帮我吗?好的

新代码:

filter([],R,_,R).
filter([Y|T],V2,Row,R):-
Y=:=0,
NewRow is Row + 1,
filter(T,V2,NewRow,R).

filter([Y|T],V2,Row,R):-
Y=\=0,
nth(Row,V2,X2),
Y=:=X2,
NewRow is Row + 1,
filter(T,V2,NewRow,R).
预期行为示例:

permutation([1,2,3,4,5,6,7,8],X),filter([1,2,3,4,0,0,0,0],X,1,R).
X = R, R = [1, 2, 3, 4, 5, 6, 7, 8] ;
X = R, R = [1, 2, 3, 4, 5, 6, 8, 7] ;
X = R, R = [1, 2, 3, 4, 5, 7, 6, 8] ;
X = R, R = [1, 2, 3, 4, 5, 7, 8, 6] .
现在我可以得到所有以1,2,3,4开头的排列。
如果有人知道更好的方法来达到同样的效果,请分享,但我已经得到了我需要的=)。

您的代码总是测试筛选列表的第一项是否为零。例如,在检查第二个值时,请查看案例:

filter([0,3,0,5,0,0,0,0], [1,2,3,4,5,6,7,8], 2).
此调用将执行以下统一:

# first case: obvious fail…
filter([0,3,0,5,0,0,0,0], [1,2,3,4,5,6,7,8], 2) =\= filter(_, _, 9).

# second case:
filter([0,3,0,5,0,0,0,0], [1,2,3,4,5,6,7,8], 2) = filter([Y|T],V2,Row).
# unification succeeds with substitutions:
    Y = 0
    T = [3,0,5,0,0,0,0]
    V2 = [1,2,3,4,5,6,7,8]
    Row = 2
# and what happens next?
    Y =:= 0 # success!
您可能想在这里检查[Y | T]的第二个元素是否为零;相反,您正在检查第一个。如果希望在不更改其余代码的情况下修复它,则应改为执行与X1的比较:

filter(V1,V2,Row):-
    nth(Row, V1, X1),
    X1 =:= 0,
    NewRow is Row + 1,
    filter(V1,V2,NewRow).

filter(V1,V2,Row):-
    nth(Row,V1,X1),
    X1=\=0,
    nth(Row,V2,X2),
    X1=:=X2,
    NewRow is Row + 1,
    filter(V1,V2,NewRow).
另外,还有一件事我想你可能还没有在Prolog中了解到。如果谓词失败,Prolog确实会打印
false
并停止计算。但如果谓词成功,则有两种情况:

  • 如果查询中没有变量,Prolog将打印
    true
  • 如果查询中有任何变量,Prolog不会打印
    true
    。而是打印变量的值。这也算作
    true

在您的例子中,Prolog实际上从谓词中“返回”
true
,只是因为您在查询中使用了变量,所以它打印了它们的值,而不是打印
true

,对于maplist/3来说似乎是一个完美的任务

filter(L1, L2, _) :-
  maplist(skip_or_match, L1, L2).

skip_or_match(E1, E2) :- E1 == 0 ; E1 == E2.
屈服

?- permutation([1,2,3,4,5,6,7,8],X),filter([1,2,3,4,0,0,0,0],X,_).
X = [1, 2, 3, 4, 5, 6, 7, 8] ;
X = [1, 2, 3, 4, 5, 6, 8, 7] ;
X = [1, 2, 3, 4, 5, 7, 6, 8] ;
X = [1, 2, 3, 4, 5, 7, 8, 6] ;
...
我们可以使用Prolog工具来实现这一点,即使用
匿名变量来表示
不在乎

然后filter/N是maplist的一个简单应用程序:

?- permutation([1,2,3,4,5,6,7,8],X),maplist(=,[1,2,3,4,_,_,_,_],X).
X = [1, 2, 3, 4, 5, 6, 7, 8] ;
X = [1, 2, 3, 4, 5, 6, 8, 7] ;
X = [1, 2, 3, 4, 5, 7, 6, 8] ;
X = [1, 2, 3, 4, 5, 7, 8, 6] ;
...

我不明白发生了什么,但是我添加了第n个谓词,但是缺少了一些文本我添加了O.O,pnuts你知道我的代码有什么问题吗?第三个参数只是一个计数器,我知道V1和v2的lgenth总是8,基本情况在那里,在过滤器之后,我只是将0改为1Hi,刚刚解决了它,我将添加代码和一个示例,但实际上我想比较以检查V1的第一个元素是否为0,因为在这种情况下,我忽略它并继续比较下一个元素,我只关心这些元素!=第0次,我知道我忘了什么,地图列表以正确的方式完成了我需要的工作