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

Prolog Recursion removing elements at index that is multiples of n from a list where n is any number

这是我第一次在这里提问,但我有一个问题,我真的无法理解这是 Prolog 递归,尤其是当它处理列表时。所以我应该解决的任务是编写一个像这样工作的 drop 谓词。例如,drop([1,2,3,4,5,6,7,8,9], 2, L) where L = [1,3,5,7,9] and N=n where elements in position 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 种情况)来检查并查看元素 return 的位置在除以 [=15 时是否为零的余数=](第二个输入)。如果它没有 return 零的余数,则 X 保留在列表中并且不会被删除。然后,序言继续进行第二个递归递归情况,它只能在 Z=0 时到达,它将 X 从列表中删除到 return Zs。本质上,索引为 n, 2n, 3n... 的元素 return 由 indexOf 编辑,如果它不 return 除以 [= 时余数为零,则将被删除15=](第二个输入)。

我目前还没有在课程的这一点上学习 Cut。如果有人能指出我正确的方向,我将不胜感激。我已经为此工作了将近一天。

我仍在努力适应这种编程范式中的逻辑和声明式思维。如果您能与我分享,我将不胜感激,您个人是如何掌握逻辑编程的?

首先,从您的方法来看,使用 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 21=]。当它成功时,下一行 Z is A 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 个元素,所以有一个计数器很有帮助,这样每次到达 N 时我都会忽略该元素。这是通过辅助谓词 drop/4 完成的,除了原始的 N:

之外,它还将有一个循环计数器
drop(L, N, R) :-
    drop(L, N, 1, R).   % Start counter at 1

基本规则

如果我从空列表中删除任何元素,我将得到空列表。我丢弃什么元素并不重要。表示为:

drop([], _, _, []).

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

递归规则 1 - 第 N 个元素

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

中删除第 N 个元素
drop([_|Xs], N, N, R) :-   % I don't care what the element is; I drop it
    drop(Xs, N, 1, R).

递归规则 2 - 除了第 N 个元素

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

Xs 中删除第 N 个元素
drop([X|Xs], N, A, [X|R]) :-
    A < N,
    NextA is A + 1,
    drop(Xs, N, NextA, R).

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