运行时出错

时间:2015-06-15 17:22:09

标签: prolog

我必须找到具有2个连续元素的排列,这些元素的差异小于3。

cons2Less3(L,Rd):-
    findall(R, (permute(L,R),(isValid(R))), Rd).

isValid([H|T]):-
    listContainsConsecLess3(T,H).

listContainsConsecLess3([H|_],C):-
    4 > abs(H - C),!.
listContainsConsecLess3([H|T],_):-
    listContainsConsecLess3(T,H).

permute(L,Rd):-
      findall(R, (perm(L,R)), Rd).

perm([],[]).
perm([E|L],Z):-
    perm(L,Z1),
    elim(E,Z,Z1).

elim(E,[E|X],X).
elim(E,[A|X],[A|Y]):-
    elim(E,X,Y).

但是在运行时:

调试:

  1 = [[6, 3, 6], [6, 6, 3], [3, 6, 6], [6, 3, 6], [6, 6, 3]]
  2 = [3, 6, 6]

控制台:

ERROR: >/2: Type error: `[]' expected, found `[3,6,6]' ("x" must hold one character)

我做错了什么?

1 个答案:

答案 0 :(得分:3)

这个诊断是代码有" findall-itis"。 :)

你从这开始:

cons2Less3(L,Rd):-
    findall(R, (permute(L,R),(isValid(R))), Rd).

假设permute/2将在回溯时单独生成每个排列。不过,您的permute/2也会调用findall/3

permute(L,Rd):-
      findall(R, (perm(L,R)), Rd).

因此perm/2会在回溯时产生单独的排列,但随后permute/2会将它们收集到一个列表中。因此,您最终调用isValid(R)并将R作为列表列表,然后:

isValid([H|T]) :-    % Called with [H|T] a list of lists
    listContainsConsecLess3(T,H).   % Called with T a list of lists

listContainsConsecLess3([H|_],C):-  % Called with H a list
    4 > abs(H - C),!.               % H is not numeric, but a list!
...

导致abs(H - C)数字表达式H作为列表产生错误。

快速解决方法是摆脱permute/2并直接致电perm/2

cons2Less3(L,Rd):-
    findall(R, (perm(L,R), isValid(R)), Rd).