Prolog:递归地构建一个列表 - 无限解决方案

时间:2014-11-03 04:26:38

标签: recursion prolog unification

我对Prolog来说是全新的,并且很难理解它的统一系统。我的问题如下:

我有一个Constraint整数,一个Source数组和一个Target数组(它们都是整数数组)。我希望过滤Source数组中的元素,以便其余元素在Target数组中具有对应元素,以便Source数组中的元素与Target数组中的元素之间的差异完全是Constraint。

示例:约束= 1,源= [1,5,7],目标= [2,3,4]。 FilteredSource应该是[1,5],因为abs(1 - 2)= 1而abs(5 - 4)= 1.目标中没有6或8,所以7不好。

根据我使用的参数,我得到错误的结果或查询得到无限循环。

到目前为止,我已经想出了这个:

filterByDistanceConstraint(_Constraint, [], _Target, _).

filterByDistanceConstraint(Constraint, [SourceHead|SourceTail], Target, FilteredSource) :-
    filterByDistanceConstraint(Constraint, SourceTail, Target, NewFilteredSource),
    ( 
        passesDistanceConstraint(Constraint, SourceHead, Target)
    ->  
        append(NewFilteredSource, [SourceHead], FilteredSource),
        filterByDistanceConstraint(Constraint, SourceTail, Target, NewFilteredSource)
    ;   
        filterByDistanceConstraint(Constraint, SourceTail, Target, FilteredSource)
    ).

passDistanceConstraint部分似乎工作正常,但我会在此处将其包含在内以供参考:

passesDistanceConstraint(_Constraint, _SourceHead, []) :-
    fail.
passesDistanceConstraint(Constraint, SourceHead, [TargetHead|TargetTail]) :-
    Distance is TargetHead - SourceHead,
    (   abs(Distance) =\= Constraint %test failed
    ->  passesDistanceConstraint(Constraint, SourceHead, TargetTail)
    ;   write('Distance constraint passed for '), write(SourceHead), nl
    ).

我很确定这是一个微不足道的问题,但我无法解决这个问题,而且我会脱掉头发。谢谢你的帮助!

1 个答案:

答案 0 :(得分:0)

这应该有效

filterByDistanceConstraint(_Constraint, [], _Target, []).

filterByDistanceConstraint(Constraint, [SourceHead|SourceTail], Target, FilteredSource) :-
    (   passesDistanceConstraint(Constraint, SourceHead, Target)
    ->  FilteredSource = [SourceHead|NewFilteredSource]
    ;   FilteredSource = NewFilteredSource
    ),
    filterByDistanceConstraint(Constraint, SourceTail, Target, NewFilteredSource).

注意第一个规则中的[]而不是_,并且第二个规则中只有一个递归调用。

'过滤器'编程模式在SWI-Prolog中通过include / 3或exclude / 3实现,但是用简单的Prolog编写,因为member / 2可以充当'枚举器':

filterByDistanceConstraint(Constraint, Source, Target, FilteredSource) :-
  findall(E, (member(E, Source), member(C, Target), abs(E - C) =:= Constraint), FilteredSource).