我正在学习序言,但遇到了一些有趣的问题。
目标是打印出家庭关系列表,
事实是:
parent(john, paul).
parent(john, mary).
parent(paul, henry).
parent(paul, june).
parent(henry, helen).
parent(mary, adam).
目标是按如下方式打印列表
L =
[john,
[paul,
[henry,
[helen]
],
[june]
],
[mary,
[adam]
]
]
这是我的代码以及我现在得到的信息,
descendantTree(X, [X|[T1]]) :- parent(X, Tmp),
descendantTree(Tmp, T1).
descendantTree(X, [X]) :- not(parent(X, Tmp)).
[debug] ?- descendantTree(john, L).
L = [john, [paul, [henry, [helen]]]] ;
L = [john, [paul, [june]]] ;
L = [john, [mary, [adam]]] ;
false.
我迷失了合并这些结果的方法,如果我能得到任何帮助,将不胜感激。谢谢!
答案 0 :(得分:0)
我认为您在这里是正确的,很明显descendantTree/2
的{{1}}的列表的第一个元素是X
本身,因此可以遵循( (可选)通过孩子列表。
我们可以通过X
调用生成这些子列表,在其中我们对自己的谓词进行递归调用,例如:
findall/3
鉴于没有“子代” descendantTree(X, [X | Ds]) :-
findall(D, (parent(X, C), descendantTree(C, D)), Ds).
,那么C
将为空,因此我们将以无子女父代为元素生成单例列表。
如果有子代,则我们将为该子代生成后代Ds
,并将每个后代添加到列表D
的末尾。通过递归执行此操作,将由此生成从给定人员到所有后代的家谱。
例如:
Ds
但是不幸的是,我们不能轻易地反向生成树:
?- descendantTree(john, L).
L = [john, [paul, [henry, [helen]], [june]], [mary, [adam]]].
此处,自由变量?- descendantTree(P, L).
L = [P, [paul, [henry, [helen]], [june]], [mary, [adam]], [henry, [helen]], [june], [helen], [adam]].
将仅匹配任何内容,因此将匹配所有P
事实。我们可以防止这种情况。我将其保留为练习。