Prolog将列表分成另外两个列表

时间:2014-12-09 21:08:09

标签: list prolog

我试图读取一个列表,检查一个元素,如果该元素在KB中,做一些事情并将其添加到另一个列表中,如果它不在KB中则添加它到另一个,第三个列表。

我一直在考虑程序逻辑,并且不能真正理解它。这是我对我有意义的 - 但它不起作用......

//KB
r([a|X],Y,[gone|X]).
r([c|X],Y,[gone|X]).
r([b|X],Y,[known|X]).
r([d|X],Y,[known2|X]).

simplify([X|List],[X|NW],Result) :-
    r(List,Nw,NewList),
    !,
    simplify2(NewList,Nw,Result).

simplify2([W|Words],Nw,[W|NewWords]) :-
     simplify2(Words,Nw,NewWords).

simplify2([],[],[]).

查询:

? - 简化([a,b,c,d,e,f],X,Y)。

我想:

X = [e,f]  
Y = [gone,known,gone,known2]

但上面给出了X = [a|mem_address]Y = [d,e]

2 个答案:

答案 0 :(得分:1)

让我们先修复语法:

  • Prolog中的其他留言评论以%而不是//开头。
  • r/3删除第二个参数;它没有目的。
  • MW - > Mw中的simplify/3
  • 在参数之间插入空格(在语法上不正确,但读取时有点挑战)。

现在让我们删除一些裁员:

  • r/2中,您并不需要列表尾部。
  • 另外,我们不需要列表来说明某些术语是已知的'或者'走了'。
  • simplify/3simplify2/3可以合并到同一个谓词中。

现在让我们添加一些新内容:

  • r/2声明为动态。这允许使用assert/1retract/1更改KB。
  • 对变量使用一致的命名。例如,H用于列表头,T用于列表尾,L用于(完整)列表。

我们得到以下信息:

:- dynamic(r/2).

r(a, gone).
r(c, gone).
r(b, known).
r(d, known2).

simplify([], [], []).
simplify([H|T1], L2, L3):-
  (   r(H, Status)
  ->  L2 = T2,
      L3 = [Status|T3]
  ;   L2 = [H|T2],
      L3 = T3
  ),
  simplify(T1, T2, T3).

具有所需的行为:

?- simplify([a,b,c,d,e,f],X,Y).
X = [e, f],
Y = [gone, known, gone, known2].

请注意上面我已经执行了以下步骤:

  1. 我试图获得语法上有效的Prolog。
  2. 一旦程序具有有效的语法,我会尝试简化它,同时保持行为稳定/完整。
  3. 只有当代码在语法上有效且简化时,我才开始改变它以实现预期的行为。
  4. 修改:感谢false指向非坚定的行为。该计划已相应编辑。

答案 1 :(得分:0)

首先,您需要使用setof从KB(实际上,常用术语是数据库)收集数据。然后很简单:

r([a|X],Y,[gone|X]).
r([c|X],Y,[gone|X]).
r([b|X],Y,[known|X]).
r([d|X],Y,[known2|X]).

kb(L) :- setof((A,B), r([A|_],_,[B|_]), L).

simplify([], [], []).
simplify([H|T], T1, [H2|T2]) :- 
    kb(L), 
    member((H,H2), L),
    simplify(T, T1, T2).

simplify([H|T], [H|T1], T2) :-
    simplify(T, T1, T2).