Prolog 列表序言中每个元素的事实

Prolog 列表序言中每个元素的事实,prolog,Prolog,我想用Prolog解决这个问题。我想给出一个自然数列表,以查找列表中满足此条件的所有元素: 它左边的所有元素都比它小,右边的所有元素都比它大。 例如,给出一个列表[3,2,4,1,5,7,8,9,10,8]答案是5,7 到目前为止,我已经设法使这个函数,给定列表中的一个元素,如果该元素满足上述条件,它将返回true或false check(Elem, List) :- seperate(Elem, List, List1, List2), lesser(Elem, List1,

我想用Prolog解决这个问题。我想给出一个自然数列表,以查找列表中满足此条件的所有元素:

它左边的所有元素都比它小,右边的所有元素都比它大。

例如,给出一个列表
[3,2,4,1,5,7,8,9,10,8]
答案是
5,7

到目前为止,我已经设法使这个函数,给定列表中的一个元素,如果该元素满足上述条件,它将返回true或false

check(Elem, List) :-
    seperate(Elem, List, List1, List2),
    lesser(Elem, List1, X1),
    bigger(Elem, List2, X2),
    size(X1, L1),
    size(X2, L2),
    size(List, L3),
    match(L1, L2, L3),
现在我想做另一个谓词,给定一个列表,它对列表中的每个元素进行上述计算。由于不止一个元素可能满足它,我想创建另一个列表,其中包含满足该问题的所有元素

问题类似于
?-谓词名称([3,2,4,1,5,7,8,9,10,8],N)。
结果是元素列表


SRY如果我没有使用Prolog的正确术语,我将用顺序逻辑语言来描述我想要做的更具体的事情,尽管这样想不是一个好主意。如果我们把谓词检查看作是给定列表和元素列表的函数,它将返回真或假,元素是否满足问题的条件。现在我想解析列表中的每个元素,并为每个元素调用函数check。如果返回true,那么我会将该元素添加到另一个列表a.k.a结果中。我想在Prolog中执行此操作,但我不知道如何迭代列表。

我将对该问题采取不同的方法

我们希望找到所有符合“中间”值标准的值,中间值定义为大于列表中所有之前的值,小于列表中所有之后的值

将谓词
mid(L,M)
定义为
M
L
的“中间”值:

mid([X|T], X) :-         % The first element of a list is a "mid" if...
    less(X, T).          %    it is less than the rest of the list
mid([X|T], M) :-         % M is a "mid" of [X|T] if...
    mid(T, X, M).        %    M is a "mid" > X
                         %    (NOTE: first element is not a "mid" by definition)

mid([X|T], LastM, X) :-  % X is a "mid" > Y if...
    X > LastM,           %    X > the last "mid"
    less(X, T).          %    X < the rest of the list, T
mid([X|T], LastM, M) :-  % Also, M is a "mid" if...
    Z is max(X, LastM),  %    Z is the larger of X and the last "mid"
    mid(T, Z, M).        %    M is the "mid" of T which is > Z

less(X, [Y|T]) :-        % X is less than the list [Y|T] if...
    X < Y,               %    X < Y, and
    less(X, T).          %    X < the tail, T
less(_, []).             % An element is always less than the empty list
然后可以使用
findall
捕获它们:

mids(L, Ms) :-
    findall(M, mid(L, M), Ns).

| ?- mids([3,2,4,1,5,7,8,9,10,8], Ms).

Ms = [5,7]

yes

| ?- mids([2], L).

L = [2]

(1 ms) yes
这可能不是计算效率最高的解决方案,因为它没有利用“mid”的两个属性。例如,“mid”将连续聚集在一起,因此一旦找到“mid”,如果随后遇到一个本身不是“mid”的元素,则继续搜索没有意义如果效率是一个目标,那么这些想法可以被运用到逻辑过程中

附录


由于@false提醒了我关于
maplist
,上面的谓词调用
less(X,T)
可以被
maplist替换(这里是一个使用DCGs的版本,假设我们想要进行算术比较

list_mid(L, M) :-
   phrase(mid(M), L).

mid(M) -->
   seq(Sm),
   [M],
   {maplist(>(M),Sm)},
   seq(Gr),
   {maplist(<(M),Gr)}.

seq([]) -->
   [].
seq([E|Es]) -->
   [E],
   seq(Es).

您的
check
关系有三个参数,但您的
check2
关系用两个参数调用它。是否希望
check
作为变量
List2
返回一个只包含一项的列表,即
Elem
?您编写的内容测试所有元素的check是否为真。您到底想要什么?不要这样做nk在“做这个做那个”中用“这意味着那个”来描述它@alpha我编辑了这篇文章,我忘记了一个参数。@用户检查工作正常。我不提供任何进一步的信息,因为它实际上做什么并不重要。现在我想做另一个谓词,给定一个列表,它对列表中的每个元素进行上述计算。对照什么列表?你是说,给定一个列表,你想运行
c吗对照完整的原始列表对列表中的每个元素进行检查
?然后在
检查2
中,如果有什么问题,您想对
检查
的结果列表做什么?我找不到文字来感谢您!非常感谢您的时间和精力effort@Mario没问题。用逻辑语言表达问题,很好地映射到prolog goe要找到解决方案还有很长的路要走。
mids([2],[2]).
失败。但左侧和右侧的所有元素都较小/较大。@false,是的,这是故意设计的。我不确定OP对极端值的作用。既然您提到了它,应该认为元素大于或小于空列表。我相应地更新了答案。酷(+1)。我正在考虑尝试DCG方法,但没有成功。哎呀,我想你指的是
maplist(>(M),Sm)
maplist(
list_mid(L, M) :-
   phrase(mid(M), L).

mid(M) -->
   seq(Sm),
   [M],
   {maplist(>(M),Sm)},
   seq(Gr),
   {maplist(<(M),Gr)}.

seq([]) -->
   [].
seq([E|Es]) -->
   [E],
   seq(Es).
mid(M) -->
   (  [M]
   |  max(Mx),
      [M],
      {Mx < M}
   ),
   min(M).

max(M) -->
   [E],
   maxi(E, M).

maxi(E, E) -->
   [].
maxi(E, M) -->
   [F],
   {G is max(F,E)},
   maxi(G, M).

min(_) -->
   [].
min(M) -->
   [E],
   {M < E},
   min(M).