List Prolog递归从n为任意数的列表中删除n的倍数索引处的元素
这是我第一次在这里问问题,但我有一个问题,我真的无法理解,那就是Prolog递归,特别是当它处理列表时。所以我要解决的任务是写一个drop谓词,它的工作原理如下。例如,List Prolog递归从n为任意数的列表中删除n的倍数索引处的元素,list,recursion,prolog,List,Recursion,Prolog,这是我第一次在这里问问题,但我有一个问题,我真的无法理解,那就是Prolog递归,特别是当它处理列表时。所以我要解决的任务是写一个drop谓词,它的工作原理如下。例如,drop([1,2,3,4,5,6,7,8,9],2,L)其中L=[1,3,5,7,9]和N=N其中元素位于位置N,2n,3n。。。。将被删除。列表从1开始是另一件需要注意的事情 以下是我迄今为止的尝试和思考过程: drop([], _, []). indexOf([X|_], X, 1). %Using 1 because t
drop([1,2,3,4,5,6,7,8,9],2,L)
其中L=[1,3,5,7,9]
和N=N
其中元素位于位置N,2n,3n。。。。将被删除。列表从1开始是另一件需要注意的事情
以下是我迄今为止的尝试和思考过程:
drop([], _, []).
indexOf([X|_], X, 1). %Using 1 because the question says the first element starts from 1.
indexOf([_|Ys], Y , I):-
indexOf(Ys, Y, N),
I is N + 1.
drop([X|Xs], Y, [X|_]) :-
indexOf([X|Xs] , X , A),
Z is A mod Y,
Z \== 0.
drop([X|Xs], Y, Zs) :-
%indexOf([X|Xs], X, A),
drop(Xs, Y, Zs).
我创建了一个indexOf
谓词来查找从1开始的元素索引。接下来,我的想法是使用我的第一个drop递归案例(在上面的代码中,它是第五个案例)来检查元素的位置在除以Y
(第二个输入)时是否返回零的余数。如果未返回零的余数,则X
将保留在列表中,并且不会被删除。然后,prolog转到第二个drop递归案例,该案例只有在Z=0
时才能到达,它将从列表中删除X
以返回Z
s。本质上,索引为n,2n,3n的元素。。。如果被Y
(第二次输入)除后未返回零的余数,则indexOf
返回的值将被删除
目前我还并没有学会这门课的这一点。如果有人能给我指出正确的方向,我将不胜感激。我已经为此工作了将近一天
我仍在尝试适应这种编程范式中的逻辑和声明性思维。如果您能与我分享,我将不胜感激,您个人是如何掌握逻辑编程的?首先,看看您的方法,使用
索引/3
有一个缺陷。也就是说,在一个给定的时间点上,当您需要知道要删除的内容的索引时,在您找到它之前,您还不知道该项目是什么。此时,索引为1
这是以下规则的一个问题:
drop([X|Xs], Y, [X|_]) :-
indexOf([X|Xs], X, A),
Z is A mod Y,
Z \== 0.
第一个子查询:indexOf([X | Xs],X,A)
第一次尝试时将成功使用A=1
,根据定义(当然,X
在列表[X | Xs]中有索引1
)
。当它成功时,下一行Z是mod Y
产生1
,因为1 mod Y
总是1
如果Y>0
。因此,在这种情况下,Z\==0
总是成功的
因此,您得到的结果是:[X |!]
其中X
是列表的第一个元素。因此,您得到的第一个解决方案,例如,drop([1,2,3,4],2,L)。
是L=[1 |
。您的第三个drop/3
谓词子句只会递归到列表中的下一个元素,因此它将以相同的方式继承第二个子句,从而产生,L=[2| |]
,依此类推
从上面开始,这里有一个方法来思考这样的问题
辅助谓词
我知道我想删除每一个N
-th元素,因此有一个计数器会很有帮助,这样每当它到达N
时,我都会忽略该元素。这是通过一个辅助谓词drop/4
完成的,除了原始N
之外,它还将有一个循环计数器:
drop(L, N, R) :-
drop(L, N, 1, R). % Start counter at 1
基本规则
如果我从空列表中删除任何元素,我将得到空列表。我删除的元素不重要。这表示为:
drop([], _, _, []).
您已经正确表达了此规则。以上是4参数版本
递归规则1-第N个元素N
-th
我有一个列表[X | Xs]
,并且X
是N
-th元素索引,如果我跳过X
,将索引计数器重置为1
,并从Xs
中删除N
-th元素,那么结果就是R
:
递归规则2-除N
-th元素之外
我有一个列表[X | Xs]
,X
是A
-th元素(N
),如果我增加我的索引计数器(A
),并用我更新的索引计数器从Xs
中删除N
-th元素,那么结果就是[X | R]
:
drop([X|Xs],N,A[X|R]):-
A
这些都是需要的规则(共4条)。你的第二个drop谓词在结果的尾部有
。
,这是不好的。这意味着你的结果会有匿名变量。所以你显然不是这个意思。把这些看作规则,并试着这样读。drop([X|Xs],Y[X||u]):-…
是列表[X | Xs]
加上Y
-th元素被删除是[X |
如果……是什么使这成为事实?当然你需要Y>1
,但是[X |
需要一个真正的尾部,尾部的值将由你的规则决定。indexOf([X | Xs],X,a)的第一个结果不是a
始终是A=1
?索引策略的一个谬误是,在你到达那里之前,你并不真正知道第Y
-th元素是什么,所以你不需要它来获取它的索引。你真的只需要一个简单的计数器。谢谢你的回答!在我再次尝试时看到了这一点今天早上,我在看gtrace,不明白为什么我的结果是[a | U G264]。多亏了你的第一句话,我现在终于明白了。我不应该在结果中使用匿名变量,因为我需要它来实例化/存储我的结果。是的!今天早上我注意到了使用indexOf策略的谬误,我尝试使用累加器作为简单计数器,但无法让它工作。不是真的
drop([_|Xs], N, N, R) :- % I don't care what the element is; I drop it
drop(Xs, N, 1, R).
drop([X|Xs], N, A, [X|R]) :-
A < N,
NextA is A + 1,
drop(Xs, N, NextA, R).