list - 如何添加和比较列表中的成员

标签 list prolog

我正在尝试编写一个谓词 is_multi(M),定义为:

  • M 的每个元素都具有 X/N 的形式,其中 X 是一个原子,N是大于0的整数;
  • M 不包含两个同原子的元素,为了什么

    is_multi([]).
    is_multi([a / 2, b / 2]).
    

    很满意,但是

    is_multi([a, b/2]).
    is_multi([a/0, b/2]).
    is_multi([a/2, 2/4])
    is_multi([a/2, b/3, a/2])
    is_multi([a/3, b/-4, c/1])
    

    不是。

这是我到目前为止所写的内容:

is_multi(M) :- M = [].
is_multi(M) :-
    M = [Head|Tail],
    Head = X/N,
    integer(N),
    N > 0,
    is_multi(Tail).

但它不会比较具有相同原子的两个元素。例如,is_multi([a/2, a/3]) 不满足。我被这个困住了一天;有人可以给我一些提示吗?

最佳答案

首先,您可以通过将一些统一从 body 移动到头部来大大简化您的代码。

is_multi([]).
is_multi([X/N|Tail]) :-
  integer(N), N > 0,
  is_multi(Tail).

清理它会发现你在这里没有做的一件事,在你的规范中检查 X 是一个原子。通过在正文中添加 atom(X) 来修复。

好的,所以这处理了基本形式,但不能确保原子不重复。最简单的做法是将其分成两项检查,一项检查每一项是否格式正确,另一项检查列表是否格式正确。事实上,我倾向于将 maplist/2 与检查单个元素的谓词一起使用。但您真正必须做的是这样的事情:

is_valid([]).
is_valid([X/_|T]) :- is_valid(T), \+ memberchk(X/_, T).

这只是说空列表是有效的,如果尾部是有效的,则如果 X over something 没有出现在尾部,则列表是有效的。

如果这就是您想要的,请停止阅读。如果您想重构,这就是我的处理方式:

well_formed(X/N) :- atom(X), integer(N), N > 0.

no_repeating_numerators([]).
no_repeating_numerators([X/_|T]) :- no_repeating_numerators(T), \+ memberchk(X/_, T).

is_multi(L) :- maplist(well_formed, L), no_repeating_numerators(L).

关于list - 如何添加和比较列表中的成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17667736/

相关文章:

Prolog:在学生的答案和成绩已知的情况下确定多项选择题测试的答案

Python:如何按每个元素的最大值对列表进行排序?

python - 如何从 BIO 分块句子中提取分块? - Python

python - 在 Python 中将字符串转换并合并到列表中

list - 对4个不同列表的元素进行分组

带索引的 Prolog 前缀

c++ - 在 C++ 中分配和释放类整数句柄的快速算法

list - F#:递归函数:测试元素是否是给定列表的成员

prolog - 与 (-)/2 运算符的差异列表

prolog - 如何在Prolog中定义一个要求所有的规则?