我是prolog的新手,我觉得很难以递归的方式思考。假设我有两个列表:list1 [0,0,0,1,1,0,1,1],list2 [1,0,1,0,0,0,1,1]。并且我想返回一个列表,当列表1或列表2在相应位置具有1时,该列表为1。
merge([H1|[]],[H2|[]],[H3|[]]):- H2 = 1, H3 = 1, H1 is 1.
merge([H1|T1],[H2|T2],[H3|T3]):- merge(T1,T2,T3), H2 = 1, H3 = 1, H1 is 1.
我知道我不能以上述形式进行翻版,但这与我现在可以接受的prolog形式非常接近。递归看起来很难!
答案 0 :(得分:2)
解决此类任务的好方法是首先描述每个列表的单个元素之间的关系,然后使用maplist/[2,3,4]
将相同的推理扩展到列表。
例如:
either_is_one(0, 1, 1).
either_is_one(1, 0, 1).
either_is_one(1, 1, 1).
但是,两个列表的 都没有" 1"在特定的位置?现在,我假设您将其与" 0":
联系起来either_is_one(0, 0, 0).
然后,我们使用maplist/4
将这些元素的列表相互关联起来:
?- maplist(either_is_one, [0,0,0,1,1,0,1,1], [1,0,1,0,0,0,1,1], Ls).
Ls = [1, 0, 1, 1, 1, 0, 1, 1] ;
false.
请注意,这是完全纯净的,也适用于其他方向。例如:
?- length(As, _), maplist(either_is_one, As, Bs, Cs).
As = Bs, Bs = Cs, Cs = [] ;
As = [0],
Bs = Cs, Cs = [1] ;
As = Cs, Cs = [1],
Bs = [0]
As = Bs, Bs = Cs, Cs = [1] ;
etc.
答案 1 :(得分:2)
使用clpb!
帽子提示@mat!事实上两次:一次到评论者,一次到clpb实施者。
:- use_module(library(clpb)). bool_bool_or(A,B,AB) :- sat(AB =:= A + B).
使用maplist/4
的示例查询:
?- maplist(bool_bool_or, [1,1,1], Bs, ABs). ABs = [1,1,1], Bs = [_X,_Y,_Z], sat(_X=:=_X), sat(_Y=:=_Y), sat(_Z=:=_Z). ?- maplist(bool_bool_or, [1,1,1], _, ABs). ABs = [1,1,1]. ?- maplist(bool_bool_or, [0,0,0,1,1,0,1,1], [1,0,1,0,0,0,1,1], ABs). ABs = [1,0,1,1,1,0,1,1].
答案 2 :(得分:1)
如何在clpfd使用合适的算术表达式?
:- use_module(library(clpfd)).
z_z_max(A,B,AB) :-
[A,B,AB] ins 0..1,
AB #= max(A,B).
使用meta-predicate maplist/3
的示例查询:
?- maplist(z_z_max, [0,0,0,1,1,0,1,1], [1,0,1,0,0,0,1,1], Ls).
Ls = [1,0,1,1,1,0,1,1]. % succeeds deterministically
clpfd提供了一个高级接口来控制流优化,这可以加快数据量级的回溯搜索速度。使用它!