我应该创建一个带整数的列表。它应该是ziga_arnitika(L,ML)。它取L列表(+)整数并返回列表ML只( - )整数列表L的偶数。 警告:X mod Y计算X:Y。
Example: ziga_arnitika([3,6,-18,2,9,36,31,-40,25,-12,-5,-15,1],ML).
ML =[-18,-40,-12]
我知道例如没有列表可以使用,但不是列表,我做的是..:
something(12) :-
write('Go to L).
something(10) :-
write('Go to Ml).
something(other) :-
Go is other -10,
format('Go to list ~w',[ML]).
答案 0 :(得分:1)
您希望计算包含满足给定列表中某些属性的元素的列表。 Prolog中的列表具有非常简单的表示。空列表由[]
表示。非空列表是由逗号分隔的元素序列。例如。 [1,2,3]
。 Prolog还提供了方便的表示法,可以在其头部(或第一个元素)和尾部(带有其余参数的列表)之间拆分列表:
?- [1,2,3] = [Head| Tail].
Head = 1,
Tail = [2, 3].
使用简单的递归谓词可以轻松地遍历列表(从其第一个元素到其最后一个元素)。很简单的情况是列表为空:
walk([]).
如果列表不为空,我们将移至列表尾部:
walk([Head| Tail]) :- walk(Tail).
但是,如果您在几乎任何Prolog系统中尝试此谓词定义,它将警告您Head
是单例变量。这意味着变量在谓词子句中出现一次。您可以通过将变量Head
替换为匿名变量(我们可以将其解释为“不关心”变量)来解决警告。因此,目前我们有:
walk([]).
walk([_| Tail]) :- walk(Tail).
我们可以使用我们的示例列表进行尝试:
?- walk([1,2,3]).
true.
Prolog是一种关系语言,如果我们用变量调用walk/1
谓词会发生什么?
?- walk(List).
List = [] ;
List = [_4594] ;
List = [_4594, _4600] ;
List = [_4594, _4600, _4606]
...
现在回到原来的问题:从其他列表的元素构建一个列表。我们想要处理输入列表的每个元素,如果它满足某些属性,则将其添加到输出列表中。我们需要两个论点。当输入列表为空时,简单的情况(或 base 情况)也是如此:
process([], []).
一般情况(或递归案例)将是:
process([Head| Tail], [Head| Tail2]) :-
property(Head),
process(Tail, Tail2).
假设谓词property/1
在其参数满足某些属性时为true。在你的情况下,是一个偶数,负整数。但并非所有元素都能满足该属性。要处理这种情况,我们需要第三个子句,它将跳过不满足属性的元素:
process([Head| Tail], List) :-
\+ property(Head),
process(Tail, List).
\+/1
谓词是Prolog标准否定谓词:当它的参数为假时它是真的。
让我们通过定义一个process/2
谓词来尝试我们的property/1
谓词,如果参数是整数零,则该谓词为真:
property(0).
示例调用将是:
?- process([1,0,2,0,0,3,4,5], List).
List = [0, 0, 0] ;
false
我们已成功编写一个谓词,从列表中提取所有零。请注意,我们的查询只有一个解决方案。如果我们在提示符下键入;
以请求下一个解决方案,Prolog顶级解释器将告诉我们没有更多解决方案(确切的打印输出取决于所选的Prolog系统;有些将打印例如{ {1}}代替no
,但含义相同)。
您现在可以通过定义合适的false
谓词来解决原始问题吗?
<强>更新强>
您可以通过编写例如:
将两个递归子句合并为一个property/1
在这种情况下,我们使用Prolog标准if-then-else 控制构造。但请注意,此构造在条件中执行隐式 cut 。即我们只采用process([Head| Tail], List) :-
( % condition
property(Head) ->
% then
List = [Head| Tail2],
process(Tail, Tail2)
; % else
process(Tail, List)
).
谓词的第一个解决方案,并丢弃任何其他可能的解决方案。使用此控件构造还可以防止在 reverse 中使用property/1
谓词(例如,使用未绑定的第一个参数和绑定的第二个参数调用它)或使用它来生成满足关系的一对术语(例如,用两个参数调用它来解析它)。这些问题可能会也可能不会很重要,具体取决于您用于过滤列表的属性以及您正在解决的实际问题的详细信息。更复杂的替代方案是可能的,但超出了这个介绍性答案的范围。