我正在使用以下代码:
item(a, b, c).
item(a, a, c).
item(a, d, c).
item(a, c, b).
main:-
getItems(L),
writeln('-----------1-------------'),
writeln(L),
findall((A,B,C), item(A,B,C), M),
writeln('-----------2-------------'),
compareItem(M,L,I),
writeln('-----------3-------------'),
writeln(I).
getItems([Item|List]):-
writeln('Enter:'),
read(Item),
dif(Item,stop),
getItems(InputList).
getItems([]).
compareItem([H|T],L,Out):-
writeln('-----------4-------------'),
intersection(H,L,I),
writeln('-----------5-------------'),
compareItem(T,L,[I|Out]).
compareItem([],L,Out).
它提供以下输出:
?- main.
Enter:
|: a.
Enter:
|: b.
Enter:
|: stop.
-----------1-------------
[a|_G1003]
-----------2-------------
-----------4-------------
-----------1-------------
[a|_G1003]
-----------2-------------
-----------4-------------
-----------1-------------
[]
-----------2-------------
-----------4-------------
false.
4 ?-
输入法取自:Creating a list from user input with swi-prolog
当命令单独运行时,我会得到以下信息:
?- findall((A,B,C), item(A,B,C), M)
M = [ (a, b, c), (a, a, c), (a, d, c), (a, c, b)].
?- intersection([a,b,c],[a,b],I).
I = [a, b].
但是,M中的[(a,b,c),...]和我预期的用户输入为[a,b](此处为空白)。
我希望输出是用户输入与M:
中每个项目的交集[(a,b), (a,a), (a), (a,b)]
此外,在到达第4点后,执行如何再次到达第1点?
如何纠正这些问题?谢谢。
答案 0 :(得分:1)
您只获得第一个元素,因为您从不使用包含其余元素的列表:
getItems([Item|List]):- writeln('Enter:'), read(Item), dif(Item,stop), getItems(InputList).
看到过于粗体的变量?它们有不同的名称,但它们需要具有相同的名称,否则您只是放弃0.7000000000
和"返回"来自InputList
的免费List
。
在编译程序时你可能已经看到了这个错误:你的Prolog发行版可能会说出以下内容:
getItems/1
这意味着这两个变量在规则中只使用一次,因此可能是错误的。
答案 1 :(得分:1)
(a,b,c)
不是Prolog中的列表。它是一个代表规范形式的术语:','(a,','(b,c))
。列表[a,b,c]
代表规范表单'.'(a,'.'(b,'.'(c,[])))
。 (a,b,c)
根本不会像列表一样,所以不会给你你想要的结果。
如果您希望将收藏集作为列表处理,请使用findall([A,B,C], item(A,B,C), M)
。
compareItem([H|T],L,[I|Out]):-
writeln('-----------4-------------'),
intersection(H,L,I),
writeln('-----------5-------------'),
compareItem(T,L,Out).
compareItem([],_,[]).
上面修复的原始谓词的另外两个问题是:
[]
是与空列表共同映射的结果。否则,Out
永远不会被实例化。I
变量,因为它需要是结果中第3个参数的头部,而不是递归调用。事实上,您可以使用maplist
执行此任务:
compareItem(M, L, Out) :-
maplist(intersection(L), M, Out).
这将缺少您的writeln
来电。如果您愿意,可以添加一个:
intersect_with_writeln(A, B, R) :-
writeln('-----------4-----------'),
intersect(A, B, R).
compareItem(M, L, Out) :-
maplist(intersect_with_writeln(L), M, Out).