问题描述
我是第一次尝试Prolog,并且在使用列表时遇到了一些困难.
I am trying out Prolog for the first time and am having a little difficulty using lists.
说我有一个元素列表.我要检查列表是否包含以下元素:
Say I have a list of elements. I want to check that the list has the following elements:
所有:A1,A2,A3,A4,A5
All of: A1, A2, A3, A4, A5
其中一个:B1,B2,B3,B4
One of: B1, B2, B3, B4
其中两个:C1,C2,C3,C4,C5,C6
Two of: C1, C2, C3, C4, C5, C6
例如,[A1,A2,B2,C1,A3,A4,C4,A5]符合要求,而[A2,A1,C1,B1,A3,A4]不符合要求.
For example, [A1, A2, B2, C1, A3, A4, C4, A5] meets the requirements and [A2, A1, C1, B1, A3, A4] does not.
如果列表满足要求,我如何写返回是/真",否则返回否/假"的东西呢?同样,编写满足要求的列表中返回缺少值的东西怎么样?
How would I got about writing something that returns Yes/True if a list meets the requirements and No/False otherwise? Similarly, how about writing something that returns the missing values from the list needed to meet the requirements?
推荐答案
您问了很多问题!让我开始为您提供一些可以满足您大部分要求的谓词.
You asked a lot of questions! Let me get you started with some predicates that solve most of your requirements.
首先让我们解决检查一个列表中的所有条目也都在另一个列表中的情况:
First let's tackle the case of checking that all entries of one list are also in the other list:
subset([ ],_).
subset([H|T],List) :-
member(H,List),
subset(T,List).
此简单的递归使用熟悉的 member/2 谓词来验证 subset/2 的第一个参数指定的列表中的每个条目也在列表中由第二个参数指定. [为简单起见,我假定这些列表的条目是不同的.如果我们要验证第一个列表的条目的多个实例至少与第二个列表中的多个实例匹配,则需要一个更详细的版本.]
This simple recursion makes use of the familiar member/2 predicate to verify each entry in the list specified by the first argument of subset/2 is also in the list specified by the second argument. [For simplicity I've assumed that entries of these list are distinct. A more elaborate version would be needed if we wanted to verify multiple instances of an entry of the first list are matched to at least that many instances in the second list.]
好吧,检查(至少)第一个列表中的一个也属于第二个列表又如何呢?显然,这是与上述谓词不同的谓词.代替第一个列表中的所有项目,如果第一个列表中的任何一个项目属于第二个列表,则要满足的目标.
Okay, how about a check that (at least) one of a first list belongs also to the second list? Obviously this is a different predicate than the one above. Instead of all items in the first list, the goal is to be satisfied if there exists any one item in the first list that belongs to the second list.
intersects([H|_],List) :-
member(H,List),
!.
intersects([_|T],List) :-
intersects(T,List).
如果此递归到达第一个参数的空列表,则该递归失败,但如果在找到第一列表的成员的第二个列表之前的任何时候成功,则该递归失败. [即使一个项目的多个实例出现在任一列表中,此谓词也能正常工作.但是,如果我们想检查第一个列表中的恰好一个项属于第二个列表,则需要完善逻辑,这将使您担心多个实例是否与确切实例一致或相反.数一.]
This recursion fails if it reaches an empty list for the first argument, but succeeds if at any point before that a member of the first list is found that belongs to the second list. [This predicate would work fine even if multiple instances of an item occur in either list. However we'd need to refine the logic if we wanted check exactly one item of the first list belongs to the second list, and that would entail worrying about whether multiple instances are consistent with or counter to the exact count of one.]
如果我们要对此检查进行概括,以验证(至少)第一个列表中的N个项目在第二个列表中,该怎么办?结果谓词将需要第三个参数:
What if we want to generalize this check, to verify (at least) N items of the first list are in the second one? The resulting predicate will require a third argument:
intersectsAtLeast(_,_,N) :- N <= 0, !.
intersectsAtLeast([H|T],L,N) :-
member(H,L),
!,
M is N-1,
intersectsAtLeast(T,L,M).
intersectsAtLeast([_|T],L,N) :-
intersectsAtLeast(T,L,N).
此递归遍历整个列表,每当第一个列表中的项目也出现在第二个列表中时,将第三个参数递减一个,并在计数减少到0(或更少)时成功. [如果列表可以重复,这里的代码又需要更多的工作.]
This recursion works through the list, decrementing the third argument by one each time an item on the first list turns out to be in the second list as well, and succeeding once the count is reduced to 0 (or less). [Again the code here needs more work if the lists can have repetitions.]
最后,您要询问编写满足要求的返回缺失值"的东西.在检查两个列表中的一个或多个项目的情况下,这没有很好地定义,因为缺失值"可能是许多可能项目中的任何一项.在特殊情况下,如果我们要求第一个列表中的所有项目都属于第二个列表,则可以确定缺失值"(如果有).
Finally you ask about writing something that "returns the missing values" need to meet requirements. This is not well defined in the case of checking for one or more items on both lists, since a "missing value" might be any one of a number of possible items. In the special case where we asked for all the items on the first list to belong to the second list, the "missing values" can be determined (if any).
missingValues([ ],_,[ ]).
missingValues([H|T],L,K) :-
member(H,L),
!,
missingValues(T,L,K).
missingValues([H|T],L,[H|K]) :-
missingValues(T,L,K).
仅当且仅当递归项未出现在第二个列表中时,才将其从输入的第一个列表移动"到输出的缺失项"第三个列表.
Here the recursion "moves" items from the input first list to the output "missing items" third list if and only if they do not appear in the second list.
关于您的问题的最后注释与符号有关.在Prolog中,变量是以大写字母或下划线开头的标识符,因此,如果将A1,A2等用作列表中的项目,则将其视为麻烦,如果将它们视为未知"而不是(我假设您的意思是)不同的原子(常数).切换到小写字母可以解决这个问题.
One final note about your questions concerns notation. In Prolog variables are identifiers that start with a capital letter or an underscore, so the use of A1, A2, etc. as items on the list is heading for trouble if those are treated as "unknowns" rather than (as I assume you meant) distinct atoms (constants). Switching to lowercase letters would solve that.
这篇关于Prolog-如何检查列表是否包含某些元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!