我正在研究一个更长的问题,我在列表表单中复制了N次元素,我相信使用append是正确的方法。 这个小谓词理论上应该是这样的:

?- repl(x,5,L).
L = [x, x, x, x, x] ;
false.

我似乎无法在网上找到任何提示,复制单个元素,但我相信我们需要使用append,但没有递归解决方案。 我来自更多的Haskell背景,这个问题会更容易执行。 有人可以帮我开始吗? :)

我的目前为止:

repl(E, N, R) :-
    N > 0, append([E], [], R), writeln(R), repl(E, N-1, R), fail.

这给了我:

?- repl(x,5,L).
[x]
[x]
[x]
[x]
[x]
false.

关闭但不完全!

===============>>#1 票数:11 已采纳

递归方法将是直截了当的并且可行。 我建议把它搞清楚。 但这是一个有趣的选择:

repl(X, N, L) :-
    length(L, N),
    maplist(=(X), L).

如果N被实例化,那么length(L, N)将生成长度为N的列表“空白”(不关心术语)。 然后maplist(=(X), L)将统一的每个元素L用变量X

这给出了一个很好的关系方法,并在一般情况下产生了明智的结果:

| ?- repl(X, N, L).

L = []
N = 0 ? ;

L = [X]
N = 1 ? ;

L = [X,X]
N = 2 ? ;
| ?- repl(X, N, [x,x,x]).

N = 3
X = x

yes
...

为了弄清楚一个递归的情况下,想想你的基本情况是什么样子(这将是repl用的计数0 - ?什么是列表的样子,然后)。 在递归的情况下,请考虑:

repl(X, N, [X|T]) :- ...

含义: 如果......,列表[X|T]是重复N次的元素X 弄清楚是什么? 如果你的基本情况是长度为0 ,那么你的递归很可能将描述repl的长度列表N的方面repl的长列表的N-1 不要忘记在这个递归规则中确保N > 0以避免回溯无限递归。 如果你不需要谓词纯粹是关系的,并假设N被实例化,那么它可以相当简单。

如果你创建一个简单的递归版本,你可以将它“包装”在这个谓词中,使其适用于变量N

repl(X, N, L) :-
    length(L, N),
    simple_recursive_repl(X, N, L).

...

因为length/2是关系的,所以它比仅提供给定列表的长度更有用。 NL未实例化时,它将成为变量列表的生成器,从长度0开始。 类型, length(L, N). 在Prolog提示下,看看会发生什么。

===============>>#2 票数:3

确定性

您给出了您想象的谓词的以下示例:

?- repl(x,5,L).
L = [x, x, x, x, x] ;
false.

请注意; 在这里效率不高。 如果你想重复x次5次,那么这可以用一种方式完成。 因此,我会将此谓词指定为确定性,而不是像您所做的那样是非确定性的

重复清单

尽管输出结果与预想的结果非常接近,但您的代码实际上距离工作解决方案还很远。 您尝试同时定义基本案例和递归案例,这将无效。

这是一个简单的(但不如@lurker给出的那样有趣:-))基本和递归情况的实现:

repeating_list(_, 0, []):- !.
repeating_list(H, Reps1, [H|T]):-
  Reps2 is Reps1 - 1,
  repeating_list(H, Reps2, T).

从某种意义上说,@ lurker的实现更简单,而且肯定更短。

一些扩展

在实际/生产代码中,您希望捕获类型错误并使用相同的谓词处理不同的实例。 第二个子句检查给定列表是否包含重复元素(如果是,那么哪一个和多少次出现)。

%! repeating_list(+Term:term, +Repeats:integer, -List:list(term)) is det.
%! repeating_list(?Term:term, ?Repeats:integer, +List:list(term)) is det.

repeating_list(_, 0, []):- !.
% The term and number of repetitions are known given the list.
repeating_list(H, Reps, L):-
  nonvar(L), !,
  L = [H|T],
  forall(
    member(X, T),
    % ==/2, since `[a,X]` does not contain 2 repetitions of `a`.
    X == H
  ),
  length([H|T], Reps).
% Repetitions is given, then we generate the list.
repeating_list(H, Reps1, [H|T]):-
  must_be(nonneg, Reps1), !,
  Reps2 is Reps1 - 1,
  repeating_list(H, Reps2, T).
% Repetitions is not `nonneg`.
repeating_list(_, Reps, _):-
  domain_error(nonneg, Reps).

请注意,如果重复次数为负,我会抛出域错误。 这在SWI-Prolog中使用库error 如果您的Prolog不支持此功能,那么您可以退出最后一个条款。

PS:与Haskell的比较

您不知道如何在Prolog中解决此问题的声明与您在Haskell中更容易解决此问题的声明的组合对我来说似乎有点奇怪。 我想你一旦知道它们两者的外观,就只能比较两种实现的难度。

===============>>#3 票数:1

我更喜欢使用findall / 3来构建列表, / 3 之间使用范围:

repl(E, N, L) :- findall(E, between(1, N, _), L).

  ask by user3290526 translate from so

未解决问题?本站智能推荐:

5回复

在Prolog中没有重复元素的两个列表的交集

我需要编写一个程序来查找两个列表的交集。 我不能使用剪切,结果列表中不应该有任何重复的元素。 这是我的代码: 当我运行以下查询时,我得到以下答案: 我能做什么? 我想得到L = [a,c]而没有别的......你能帮忙吗?
1回复

Prolog在列表中重复一个单词

我有一个Prolog代码,可以复制整个列表,但是我想要的是仅复制一个单词(例如“ a”)。 例如; 我的代码重复了列表[a,b]例如=> [a, a ,b ,b] 。 但是我想要的是重复列表[a, b]例如=> [a, a, b] 。
2回复

Prolog - 在列表中创建累积重复项?

我有一个列表L给我,我的任务是创建累积重复,取决于我想要多少。 我有列表[a,b,c,d]例如,并希望第一个元素重复4次(可选),然后每个后续元素必须像前一个+ 1一样重复。 假设我的谓词叫做list_copy(L,N,R) , L = [a,b,c,d]和K = 2应该是:
2回复

Prolog:采用两个元素的列表,并且仅当第一个元素与第二个元素相同时才返回true

我是一名新手Prolog程序员,对于一项作业,我必须拥有一个基本程序,该程序必须且仅当list X是两个元素的列表且第一个元素与第二个元素相同时才能成功。 从我的序言的角度来看,程序似乎很小,所以我输入了以下内容: 当我在swipl下运行它时,我将其作为输出: 还有什么需要
2回复

从列表中删除重复项,但在SWI-Prolog中不返回两个相同的结果?

我写这个谓词是为了从列表中删除重复项,但是当我测试它时, 有没有办法只保留一个结果,而不是两个相同的结果? (因此它只会返回一个列表)。 另外,不允许我使用修改回溯搜索的运算符,例如cut运算符!,否定运算符not,+或if-then-else运算符->和; 如果有
1回复

如何从序言列表中删除所有重复项

我有一个列表,比方说X=[a,b,c,d,c,e,d] ,如何删除每个字符中的一个,所以唯一的答案仍然是X1=[c,d] 。 我有一堆只包含字母的列表,我需要一个命令,如果列表中包含每个字母,那么它将删除每个单个字母,如果没有一个字母,则不执行任何操作。 我尝试selectchk/3
2回复

Prolog - 只减去每个项目一次

当我使用prolog的内置谓词“减去/ 3”时:例如减去(+ Set,+ Delete,-Result): 但我想在+设置ONCE中删除+删除中的每个项目。 我的意思是,我想要 我怎样才能做到这一点?
1回复

从列表序言中删除相邻重复项

我是Prolog的新手,我需要从列表中删除重复项,如下面的示例所示。
1回复

从使用Findall生成的列表中删除重复项

我正在通过提供一个非常简单的数据库来记录和发送电子邮件,以此来练习Prolog。 我创建使用列表findall预先指定的接收器的X 。
2回复

如何使用递归将多个头添加到列表中

我想从列表A和B中删除每个第n个元素,这些元素与彼此的第n个元素不对应。 例如:我有包含[1,2,3,4,5]列表A和包含[1,2,2,4,7]列表B 结果应该是包含[3,5]列表C和包含[2,7]列表D 我想出了这段代码,但它还没有正常工作。 而不是[3,5]和[2,7] ,我得