Prolog递归从索引中删除元素,索引是n的倍数,其中n是任意数字

时间:2015-03-03 19:42:38

标签: 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 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递归情况(在上面的代码中是第5个案例)来检查并查看元素的位置在除以Y(第二个)时是否返回零的余数输入)。如果它没有返回零的余数,则X保留在列表中并且不会被删除。然后,prolog转到第二个递归递归的情况,该情况只能在Z=0时到达,并且它将从列表中删除X以返回Z s。本质上,indexOf返回的索引为n,2n,3n ...的元素如果在除以Y(第二个输入)时没有返回零的余数,则将被删除。 / p>

此刻我还没有学过Cut。如果有人能指出我正确的方向,我将不胜感激。我已经在这方面工作了将近一天。

我仍在尝试在这种编程范式中调整逻辑和陈述性思维。如果你能和我分享,我很感激,你个人如何掌握逻辑编程?

1 个答案:

答案 0 :(得分:0)

首先,看看你的方法,使用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在列表{{1}中有索引1成功后,下一行[X|Xs]会产生Z is A mod Y,因为如果1 1 mod Y总是1。因此,Y > 0会在这种情况下总能成功。

因此,您得到结果:Z \== 0其中[X|_]是列表的第一个元素。因此,您获得的第一个解决方案,例如Xdrop([1,2,3,4], 2, L).。你的第三个L = [1|_]谓词子句只是递归到列表中的下一个元素,那么它将以相同的方式继承第二个子句,产生drop/3,等等......

从顶部开始,这是一种思考像这样的问题的方法。

辅助谓词

我知道我想要删除每个L = [2|_]个元素,因此有一个计数器是有帮助的,这样每次到达N时我都会忽略该元素。这是通过辅助谓词N完成的,除了原始drop/4之外,它还有一个重复的计数器:

N

基本规则

如果我从空列表中删除任何元素,我会得到空列表。我放弃的元素并不重要。这表达为:

drop(L, N, R) :-
    drop(L, N, 1, R).   % Start counter at 1

您已经正确表达了此规则。以上是4参数版本。

递归规则1 - drop([], _, _, []). - 元素

我有列表N[X|Xs]是第X个元素索引,如果我跳过N,结果为R,将我的索引计数器重置为X,并从1 中删除N个元素:

Xs

递归规则2 - 除了drop([_|Xs], N, N, R) :- % I don't care what the element is; I drop it drop(Xs, N, 1, R). - 元素

之外

我有列表N[X|Xs]X - 元素(< A),那么结果是N我增加了我的索引计数器([X|R]),并使用我更新的索引计数器删除A中的N元素:

Xs

这些是所有必需的规则(其中4个)。