3

我想为 这个论坛中的其他一些最近的问题提供一个逻辑上纯粹的解决方案。

首先,我实现了一个具体化的变体append/3并将其命名为appendR/4. 它基于谓词if_/3并由(=)/3AUBUC 的Prolog union 中的 @false 实现

appendR([],Ys,Zs,T) :- 
    =(Ys,Zs,T).
appendR([X|Xs],Ys,ZZs,T) :-
    if_([X|Zs] = ZZs, appendR(Xs,Ys,Zs,T), T = false).

该实现基本上可以工作,如以下查询所示:

?- appendR([1,2],Ys,[2,3,4],T).
T = false ? ;
no

?- appendR([1,2],[3,4],Xs, T).
T = true,  Xs = [1,2,3,4],                       ? ;
T = false, Xs = [1,2|_A],  prolog:dif([3,4],_A)  ? ;
T = false, Xs = [1|_A],    prolog:dif([2|_B],_A) ? ;
T = false,                 prolog:dif([1|_A],Xs) ? ;
no

到目前为止,一切都很好......这是棘手的部分:

?- appendR([1,2],Ys,[1,2,3,4],T).
T = true,  Ys = [3,4]                   ? ;
T = false, prolog:dif(Ys,[3,4])         ? ;
T = false, prolog:dif([2|_A],[2,3,4])   ? ;
T = false, prolog:dif([1|_A],[1,2,3,4]) ? ;
no

我想得到前两个答案,但不是最后两个。请帮忙!

4

2 回答 2

1

我还编写了一个替代变体appendRR/4

appendRR([],Ys,Zs, T) :- 
    =(Ys,Zs,T).
appendRR([_|_],_,[], false).
appendRR([X|Xs],Ys,[Z|Zs], T) :-
    if_(X=Z, appendRR(Xs,Ys,Zs,T), T = false).

它没有给出多余的答案:

?- appendRR([1,2],Ys,[1,2,3,4],T).
T = true,  Ys = [3,4]           ? ;
T = false, prolog:dif(Ys,[3,4]) ? ;
no

然而,目标appendRR([1,2],_,foo,T)失败了。我宁愿得到答案T = false。这让我有些烦恼。

appendRR如果调用者可以保证非列表项永远不会用作 的第三个参数,我仍然觉得可以容忍appendRR/4

于 2015-04-07T13:33:50.380 回答
1

下次试试:append_t/4。它应该结合 和 的“最佳appendR/4appendRR/4

首先,我们定义了具体化的非空列表测试谓词cons_t/2

cons_t(V,T) :- 
   (  nonvar(V)                         % we can decide right now!
   -> (  V = [_|_]
      -> T = true
      ;  T = false
      )
   ;  V = [_|_],          T = true      % go nondet!
   ;  freeze(V,V\=[_|_]), T = false
   ).

基于cons_t/2, (=)/3,if_/3我们定义append_t/4如下:

append_t([],Bs,Cs,T) :-
   =(Bs,Cs,T).
append_t([A|As],Bs,Cs0,T) :-
   if_(cons_t(Cs0),
       (Cs0=[C|Cs], if_(A=C, append_t(As,Bs,Cs,T), T=false)),
       T=false).

让我们查询并比较我们得到的答案!错误的结果被突出显示(用粗体字写成)。

  1. ?- appendR([1,2],[3,4],Cs,T)。
      T = 真,Cs=[1,2,3,4]
    ; T = 假,Cs=[1,2|_X] ,差异(_X,[3,4])
    ; T = 假,Cs=[1|_X] ,差异(_X,[2|_])
    ; T = 假,差异(Cs,[1|_])。
    
    ?- appendRR([1,2],[3,4],Cs,T)。
      T = 假,Cs = []
    ; T = 假,Cs = [1]
    ; T = 真,Cs = [1,2,3,4]
    ; T = 假,Cs = [1,2|_X] ,差异(_X,[3,4])
    ; T = 假,Cs = [1,_X|_] ,差异(_X,2)
    ; T = 假,Cs = [_X|_] ,差异(_X,1)。
    
    ?- append_t([1,2],[3,4],Cs,T)。
      T = 真,Cs = [1,2,3,4]
    ; T = 假,Cs = [1,2|_X] ,差异(_X,[3,4])
    ; T = 假,Cs = [1,_X|_] ,差异(_X,2)
    ; T = 假,Cs = [1|_X] ,冻结(_X,_X\=[_|_])
    ; T = 假,Cs = [_X|_] ,差异(_X,1)
    ; T = 假,冻结(Cs,Cs\=[_|_])。
    
  2. ?- appendR([1,2],Bs,[1,2,3,4],T)。
      T = 真,Bs=[3,4]
    ; T = 假,差异(Bs,[3,4])
    ; T = 假
    ; T = 错误。
    
    ?- appendRR([1,2],Bs,[1,2,3,4],T)。
      T = 真,Bs=[3,4]
    ; T = 假,差异(Bs,[3,4])。
    
    ?- append_t([1,2],Bs,[1,2,3,4],T)。
      T = 真,Bs=[3,4]
    ; T = 假,差异(Bs,[3,4])。
    
  3. ?- appendR([1,2],_,[2,3,4],T)。
    T = 错误。
    
    ?- appendRR([1,2],_,[2,3,4],T)。
    T = 错误。
    
    ?- append_t([1,2],_,[2,3,4],T)。
    T = 错误。
    
  4. ?- appendR([1,2],_,non_list,T)。
    T = 错误。
    
    ?- appendRR([1,2],_,non_list,T)。
    错误的。
    
    ?- append_t([1,2],_,non_list,T)。
    T = 错误。
    

总结: appendR/4appendRR/4在一些测试用例中失败,append_t/4并没有。

于 2015-10-24T11:53:42.687 回答