如何从序言中的两个列表构造一个列表

How to construct a list from two lists in prolog

我是 prolog 的新手,我发现很难以递归的方式思考。假设我有两个列表:list1[0,0,0,1,1,0,1,1], list2[1,0,1,0,0,0,1,1]。当 list1 或 list 2 在相应位置有 1 时,我想 return 有一个 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.

我知道我不能在上面的形式中扭动,但这是我现在能做的最接近序言形式的形式。递归看起来太难了!

解决此类任务的一个好方法是首先描述每个列表的单个元素之间的关系,然后使用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.

如何使用合适的算术表达式

:- use_module(library(clpfd)).

z_z_max(A,B,AB) :-
   [A,B,AB] ins 0..1,
   AB #= max(A,B).

示例查询使用 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

提供了一个高级接口来控制流程优化,可以按数量级加速回溯搜索。使用它!

使用!

向@mat 致敬!事实上,两次:一次给评论者,一次给 实施者。

:- 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].