【问题标题】:Combining predicates in Prolog在 Prolog 中组合谓词
【发布时间】:2017-02-03 21:59:48
【问题描述】:

我必须创建一个谓词reverseeven(List, Reversed),仅当列表具有偶数个元素时才会反转列表,否则将返回空列表。 我有一个函数可以确定列表是否有偶数个元素和一个反向函数:

evenlength([_,_]).
evenlength([_,_|X]):-
    evenlength(X).

reverse([_,_],R).
reverse([H|T], R):-
    reverse(T,ReverseT), append(ReverseT, [H], R).

但我不确定如何将两者结合起来。

【问题讨论】:

    标签: list recursion prolog reverse


    【解决方案1】:

    您不能“组合”谓词,但您可以在两个(或多个)谓词之间进行逻辑连接,只有当它们都成功时才会成功:

    reverseEven(List, Reversed) :- 
          evenlength(List),            % This must succeed 
          reverse(List, Reversed).     % and this one in order this case to succeed
    
    reverseEven(_, []).                % this will succeed otherwise
    

    以上不是最有效的实现(例如,您可以在检查偶数长度后使用 cut ! 运算符)。但它显示了这个想法。

    更新 顺便说一句,您的 reverse 谓词应该如下所示:

    reverse([],[]).    % Empty list is a reverse of empty list
    reverse([H|T], R):-
        reverse(T,ReverseT), append(ReverseT, [H], R).    
    

    更新 2 感谢@Lurker。上面的代码将产生两个答案。第一个将是正确的。如果我们要求 Prolog 进一步搜索,它将找到另一个空列表的答案,因为第二个子句总是正确的。为了解决这个问题,我们可以显式检查列表的长度是否使用否定运算符,或者我觉得更优雅的只是为空列表添加另一个子句,而对于非偶数检查只需使用现有的 evenlength 和带有额外元素的列表:

    reverseEven([], []).  
    reverseEven(List, Reversed) :- 
        evenlength(List),            % This must succeed 
        reverse(List, Reversed).     % and this one in order this case to succeed
    
    reverseEven([H|T], []) :- 
        evenlength([H|[H|T]]).
    

    【讨论】:

    • 不幸的是,这段代码为reverseEven([a,b], R) 生成了两个解决方案。一个是正​​确的(R = [b,a]),另一个是不正确的,R = []。
    • @lurker 你是对的,谢谢。将更新答案,尽管它并不是问题的真正重点。
    • 我同意这不是重点,但是在提供解决方案时,最好解决方案是正确的,或者明确说明它不正确或不完整,并将其留作 OP 的练习找到一个完整的解决方案。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多