关于在Prolog中合并列表

时间:2018-10-16 19:21:10

标签: prolog

我正在学习序言,但遇到了一些有趣的问题。

目标是打印出家庭关系列表,

事实是:

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.

我迷失了合并这些结果的方法,如果我能得到任何帮助,将不胜感激。谢谢!

1 个答案:

答案 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事实。我们可以防止这种情况。我将其保留为练习。