Prolog - 将列表中的元素添加到另一个列表而不重复

时间:2017-04-11 10:05:51

标签: prolog

这是我的代码:

students([], NameList).
students([Name1+Name2+_|MoreProjects], [Name1,Name2|NameList]) :-
     not_member(Name1, NameList),
     not_member(Name2, NameList),
     students(MoreProjects, NameList).
students([Name1+Name2+_|MoreProjects], [Name1|NameList]) :-
     not_member(Name1, NameList),
     not(not_member(Name2, NameList)),
     students(MoreProjects, NameList).
students([Name1+Name2+_|MoreProjects], [Name2|NameList]) :-
     not(not_member(Name1, NameList)),
     not_member(Name2, NameList),
     students(MoreProjects, NameList).
students([Name1+Name2+_|MoreProjects], NameList) :-
     not(not_member(Name1, NameList)),
     not(not_member(Name2, NameList)),
     students(MoreProjects, NameList).

not_member(_, []).
not_member(X, [Head|Tail]) :-
      X \= Head,
     not_member(X, Tail).

它应该做的是检查Name1或Name2是否已经在未绑定列表中,并将其添加到结果中。

运行此合法查询

students([ Dickens+Joyce+1,
           Chekhov+Tolstoy+2,
           Austen+Shakespeare+3,
           Shirley+Byron+4
         ],
        StudentList).

只是给我假。我该如何调整编码?

1 个答案:

答案 0 :(得分:1)

问题在于你无法测试Name1之类的元素是否是Namelist中的成员,因为Namelist没有实例化,这在使用否定时会导致问题。例如,尝试:

?- member(a,L).
L = [a|_G6809] .

成功假设L是[a | _G6809],所以它部分实例化L,但现在尝试:

?- \+member(a,L).
false.

这不能做任何失败的事情。您已经多次使用过这样的:not(not_member(Name2, NameList)),因为NameList没有实例化,所以会失败,因为上面的例子。

为了修复你需要另一个List-accumulator你将存储你找到的所有元素,并且它将在每一步完全实例化,这样你就可以检查一个元素是否是成员:

students(L1,L2):-students(L1,L2,[]).

students([], L, L).
students([Name1+Name2+_|MoreProjects], NameList, L):-
     not_member(Name1, L),
     not_member(Name2, L),
     students(MoreProjects, NameList,[Name1,Name2|L]).

students([Name1+Name2+_|MoreProjects], NameList, L):-
     not_member(Name1, L),
     not(not_member(Name2, L)),
     students(MoreProjects, NameList, [Name1|L]).

students([Name1+Name2+_|MoreProjects], NameList, L):-
     not(not_member(Name1, L)),
     not_member(Name2, L),
     students(MoreProjects, NameList, [Name2|L]).

students([Name1+Name2+_|MoreProjects], NameList, L):-
     not(not_member(Name1, L)),
     not(not_member(Name2, L)),
     students(MoreProjects, NameList, L).

not_member(_, []).
not_member(X, [Head|Tail]) :-
      X \= Head,
     not_member(X, Tail).

在上面我们开始在必要时给第三个参数作为空列表添加元素。

此外,当您尝试查询时

students([ Dickens+Joyce+1,
           Chekhov+Tolstoy+2,
           Austen+Shakespeare+3,
           Shirley+Byron+4
         ],
        StudentList).

请注意,无论以大写字母开头的是Prolog中的变量,您都需要查询: 学生([“狄更斯”+“乔伊斯”+1,            “契诃夫” + “托尔斯泰” +2,            “奥斯汀” + “莎士比亚” +3,            “雪莉” +“拜伦” +4          ]         StudentList)。 现在让我们试试吧:

students([ "Dickens"+"Joyce"+1,"Chekhov"+"Tolstoy"+2, "Auste"+"Shakespeare"+3,"Shirley"+"Byron"+4 ], StudentList).
StudentList = ["Shirley", "Byron", "Auste", "Shakespeare", "Chekhov", "Tolstoy", "Dickens", "Joyce"] ;
false.

?- students([ "Dickens"+"Joyce"+1,"Byron"+"Tolstoy"+2, "Byron"+"Shakespeare"+3,"Byron"+"Byron"+4 ], StudentList).
StudentList = ["Shakespeare", "Byron", "Tolstoy", "Dickens", "Joyce"] ;
false.
相关问题