我必须找到具有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)
我做错了什么?
答案 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).