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 Z
s。本质上,索引为 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 个)。
这是我第一次在这里提问,但我有一个问题,我真的无法理解这是 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 Z
s。本质上,索引为 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 个)。