Prolog中获取指定节点三级好友列表的技术求助
搞定Prolog三级好友列表的问题
嘿,我来帮你解决这个Prolog里的好友列表问题!首先咱们得明确你要的三级好友是啥:就是和a的关系距离在1到3之间的人——直接好友(距离1)、好友的好友(距离2)、好友的好友的好友(距离3),而且你要的结果刚好排除了更远的e、f,完全符合你的期望。
先看你现有的好友事实:
friend(a,b). friend(a,b2). friend(a,b3). friend(b,c). friend(c,d). friend(d,e). friend(e,f).
方法一:自定义递归的层级好友谓词
咱们可以先写一个friend_at_level/3的谓词,专门用来找某个人的第N级好友:
% 第1级就是直接好友,直接匹配friend事实 friend_at_level(Person, Friend, 1) :- friend(Person, Friend). % 第N级好友:先找到第N-1级的中间好友,再找这个中间好友的直接好友 friend_at_level(Person, Friend, N) :- N > 1, N1 is N - 1, friend_at_level(Person, Intermediate, N1), friend(Intermediate, Friend), Friend \= Person. % 防止出现自己加自己为好友的情况(如果有环的话)
接下来,咱们要把1到3级的所有好友捞出来,还要去重(虽然你现在的例子没重复,但万一有环呢?)。用findall/3配合between/3遍历1-3级,再用sort/2去重排序:
get_three_level_friends(Person, Friends) :- findall(F, (between(1,3, Level), friend_at_level(Person, F, Level)), UnsortedList), sort(UnsortedList, Friends).
现在测试一下:
?- get_three_level_friends(a, List). List = [b, b2, b3, c, d].
完美命中你要的结果!
方法二:用闭包简化(适合SWI-Prolog这类支持closure/3的环境)
如果你用的是SWI-Prolog,它自带的closure/3可以直接处理关系的传递闭包,咱们只要限制传递步数在3以内就行:
get_three_level_friends(Person, Friends) :- findall(F, ( closure(friend, Person, F), % 计算Person到F的关系距离,确保不超过3 distance(Person, F, D), D =< 3 ), UnsortedList), sort(UnsortedList, Friends). % 辅助谓词:计算两个节点之间的关系距离 distance(Person, Person, 0). distance(Person, Friend, D) :- friend(Person, Intermediate), distance(Intermediate, Friend, D1), D is D1 + 1.
运行这个查询,同样会得到你想要的列表。
小提醒
- 去重很重要:
sort/2不仅能给列表排序,还会自动删掉重复元素,要是你的好友关系有环(比如friend(b,a)),这一步就会避免把a自己加到列表里,也不会重复出现同一个好友。 - 排除自身:在第一个方法里加了
Friend \= Person,也是为了防止出现自己成为自己好友的奇怪情况。
这样就能轻松获取你需要的三级好友列表啦!
内容的提问来源于stack exchange,提问作者Daniel Fialho
相关产品推荐
相关产品推荐

