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次,我知道我忘了什么,地图列表以正确的方式完成了我需要的工作