【问题标题】:Prolog Recursion through Set ofProlog 递归通过 Set
【发布时间】:2020-03-12 07:29:32
【问题描述】:

我正在尝试处理这个 Prolog 规则,你传入一个电影列表的输入,它会返回一个涉及该特定电影的明星列表。

谓词:

starsin(captain_america,chris_evan).
starsin(avengers,chris_evan).
starsin(ant_man,chris_evan).
starsin(captain_marvel,chris_evan).
starsin(iron_man,chris_evan).
starsin(avengers,tom_holland).
starsin(captain_marvel,tom_holland).
starsin(captain_america,tom_holland).
starsin(iron_man,robert).
starsin(avengers,robert).
starsin(captain_america,robert).

我尝试使用一组规则,但不知何故我无法找到递归使用它的方法:

link([Head],Set) :-
   setof(Star1,starsin(Head,Star1),Set).

输入和输出:

link([ironman],Set).
Set=[chris_evan,robert]

不知何故,我想在列表中传递多个元素,但我需要使用递归。

有没有我能做到的?

【问题讨论】:

  • 如果您有不止一部电影会怎样?您的link 谓词是否给出了所有电影中的一组人,还是他们只需要出现在其中一个电影中?
  • 所以我想要的是输入是电影列表,输出将是出现在给定电影中的明星列表,例如输入:[ Captain_america, avengers, ant_man ] 输出将是[chris_evan]

标签: recursion prolog


【解决方案1】:

你有一个不确定的谓词starsin(X, Y) iff 电影X 包括电影明星Y

让我们概括一下,告诉我们哪些明星出现在任何电影列表中。

movies_starsin(Movies, Star) :-
    member(Movie, Movies),
    starsin(Movie, Star).

最后你想要这样的东西:

movies_stars(Movies, Stars) :-
    setof(Star, movies_starsin(Movies, Star), Stars).

希望这会有所帮助。

[更新]

我误解了这个问题,即在给定列表中找到出现在所有部电影中的一组明星。好的:

starsin_all([Movie | Movies], Star) :-
    % Star must appear in Movie.
    starsin(Movie, Star),
    % There can be no OtherMovie in which Star does not appear.
    \+ (
        member(OtherMovie, Movies),
        \+ starsin(OtherMovie, Star)
    ).

all_starsin_all(Movies, Stars) :-
    setof(Star, starsin_all(Movies, Star), Stars).

你可以这样写starsin_all

starsin_all([Movie | Movies], Star) :-
    starsin(Movie, Star),
    forall(member(OtherMovie, Movies), starsin(OtherMovie, Star)).

干杯。

【讨论】:

  • 听起来他们只想要所有电影中的明星。
  • 它以某种方式起作用,但是当我使用以下查询对其进行测试时:movies_stars([ironman,avengers,captain_marvel,ant_man],Stars)。它应该只输出为 [chris_evan]。但在您的代码中,它会输出每部电影中的所有明星
  • 哦,你想要每部电影的明星的交集。让我编辑我的答案。
  • 没有涵盖“输入列表中没有电影”的特殊情况,需要添加一个事实:starsin_all([], Actor) :- starsin(_, Actor). ..我允许自己将这个解决方案添加到我的小github page ,其中还包含单元测试代码。
【解决方案2】:

您可能想要maplist/2 之类的东西,它可用于查找适用于列表中所有 成员的解决方案,这正是您想要的。然后,因为你想要所有的星星,也许像findall/3

我建议更改 starsin 以将演员放在第一位,原因有两个: 1. 说“钢铁侠中的克里斯埃文明星”比反过来说更有意义。例如。相比之下,member(X, S) 表示“X 是 S 的成员”。 2. 使用maplist 会更轻松。

不会给你完整的解决方案,因为这看起来有点功课。 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-07
    • 2017-04-26
    • 2011-12-09
    • 2014-06-16
    • 2018-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多