我想制作一个Prolog程序,我有一个" Person"那"看了" "影#34 ;.
我希望像watched(person's code, [movie code 1, movie code 2])
一样写它,这样我就可以为每个人写一个观看电影的列表,而不是写很多行。
我有这些movie/2
事实:
% movie(code, movie's name).
movie(1, 'Thor 1').
movie(2, 'Thor 2').
movie(3, 'Captain America').
movie(4, 'Captain America 2').
这些person/2
事实:
% person(code, persons's name).
person(1, 'ana').
person(2, 'john').
以及这些watched/2
事实:
% watched(person's code, movie's code).
watched(1, [1,2,3]).
watched(2, [1,2,4]).
如你所见,Ana例如观看了电影“Thor 1',' Thor 2'和'美国队长'。
我试图查询以下内容:
?- watched(P, [X,Y,Z]), movie(Z,N), Z is X, Z is Y.
但是prolog不会接受它。
有没有办法将两个变量分配给一个?与Z is X, Z is Y
另外,如果我查询:
(_, [ _ ,_,Z| _ ]) = (_, [1, 2, 3, 4]), movie(Z,N).
prolog将返回一部电影,但只有一部电影,而(_, [ _, _|Z])
无法播放多部电影。
答案 0 :(得分:1)
好的,所以您希望能够查询watched_movie('ana', 'Thor 2')
形式的内容。让我们来看看所涉及的步骤。
watched_movie(P, M) :-
,其中P是人物的姓名,M是电影名称。参数是名称,但数据使用ID。因此,让我们将名称转换为ID:
person(PId, P),
movie(MId, M),
这将查看数据库以获取相应的ID和名称。
从这些ID对中,谓词只有在此人实际观看过该电影时才会成功。为此,只需从数据库中获取观看的电影列表,并检查它是否包含电影ID。
watched(PId, Movies),
member(MId, Movies).
(member
是一个内置的prolog谓词;但我鼓励你自己编写它作为练习。)
就是这样。把它们放在一起,谓词看起来像这样:
watched_movie(P, M) :-
person(PId, P),
movie(MId, M),
watched(PId, Movies),
member(MId, Movies).
现在您可以查询所需的一切。
?- watched_movie('ana','Thor 2').
true.
?- watched_movie(P, 'Thor 2').
P = ana;
P = john.
?- watched_movie('ana', M).
P = 'Thor 1';
P = 'Thor 2';
P = 'Captain America'.
?- watched_movie(P, M).
M = 'Thor 1',
P = ana;
...
至于你的尝试:
watched(P, [X,Y,Z]), movie(Z,N), Z is X, Z is Y.
在这里,您可以查询已经观看过3部电影的人(因为列表正是那么长),但是当您放置Z is X, Z is Y
时,您基本上会说所有3部电影都必须相同。您的数据库中没有此类数据,因此查询失败。
(_, [ _ ,_,Z| _ ]) = (_, [1, 2, 3, 4]), movie(Z,N).
虽然这是有效的prolog,但这个查询的第一部分真正做的唯一事情就是说Z == 3.第二部分得到这部电影的名称,ID为3,因为只有一部分你得到的确切结果。
答案 1 :(得分:1)
@Steven的answer涵盖了有关此问题的所有内容,但是阅读看起来像OP的评论仍然对Prolog找到的不同解决方案感到困惑:
"是的,但我希望在剧情时间与多部电影联系。"
"那么,用
document.Content.Text
创建数据库的唯一方法是写出很多行?所以,如果有人观看了6部电影,那就是:watched
?"
似乎你想要完成的是获得给定人物的所有观看电影,而不是获得单独的答案。为此,您可以使用额外逻辑的全解决方案谓词。我们来看看它对您的代码的用途。
使用@ Steven的谓词(平凡编辑):
watched(1, 1). watched(1, 2). watched(1, 3). watched(1, 4). watched(1, 5).
我们现在只需环绕person_watched_movie(P,M) :-
person(PId,P),
watched(PId,MovieIds),
member(MId,MovieIds),
movie(MId,M).
谓词:
findall/3
现在,您可以获取某人/每个人/ ...一次观看的电影列表:
person_watched_movies(Person,Movies) :-
findall(Movie,person_watched_movie(Person,Movie),Movies).
让我们考虑一下一般的查询,当我们要求Prolog找到任何人看过的电影时会发生什么?好吧,它应该给我们任何电影中至少观看过一次的事实 - 请注意,由于多人可以观看同一部电影,因此可能会出现重复的电影。我们来试试吧!
?- person_watched_movies('ana',M).
M = ['Thor 1', 'Thor 2', 'Captain America'].
大!接下来,我们还可以使用此谓词快速获取某些特定人员观看的电影列表:
使用析取运算符:
?- person_watched_movies(X,Y).
Y = ['Thor 1', 'Thor 2', 'Captain America', 'Thor 1', 'Thor 2', 'Captain America 2'].
或等效地,使用?- (X='ana' ; X='john'), person_watched_movies(X,Y).
X = ana,
Y = ['Thor 1', 'Thor 2', 'Captain America'] ;
X = john,
Y = ['Thor 1', 'Thor 2', 'Captain America 2'].
和列表:
member/2
最后,如果您想同时检索观看电影的人,您可以使用?- member(X,['ana','john']), person_watched_movies(X,Y).
X = ana,
Y = ['Thor 1', 'Thor 2', 'Captain America'] ;
X = john,
Y = ['Thor 1', 'Thor 2', 'Captain America 2'].
表示法,如下所示:
-/2
当给出我们之前使用的相同的一般查询时,这将改为输出:
person_watched_movies(Person,Movies) :-
findall(Person-Movie,person_watched_movie(Person,Movie),Movies).
希望这有帮助!