prolog - 如何在序言中制作特定长度的随机列表而不重复?

标签 prolog

我正在尝试编写一个谓词randomnames/1,它生成三个不同名称的随机列表。这些名称位于数据库中,并且我已经有了一个随机名称的谓词:

name(1, Mary).
name(2, Pat).
name(3, James).
name(4, Bob).
name(5, Susan).

random_name(Name):- 
  random(0, 6, N),    
  name(N, Name). 

为了将其列入列表,有人建议我应该这样做:

random_names([A,B,C]) :-
    random_name(A),
    random_name(B),
    random_name(C).

唯一的问题是生成的列表中可能会出现重复项。我不知道如何解决这个问题。我可以编写一个新谓词来删除重复项,但是如何用另一个变量替换重复项,以便列表仍然具有三个元素?当 random_names 谓词中没有明确的头和尾时,我该如何编写删除谓词?

最佳答案

在 Prolog 中编程时,请考虑您的解决方案必须满足的条件

目前,您已经了解如何描述包含三个元素的列表,其中每个元素都是一个随机名称。

这是一个好的开始,但还不够:此外,您现在想要描述元素成对不同的条件。

所以,考虑一下如何描述一个包含三个元素的列表,其中所有元素都是成对不同的。

我给你一个开始,使用 dif/2 以合理的方式表达术语的不平等(参见 ):

three_distinct_elements([A,B,C]) :-
        dif(A, B),
        dif(A, C),
        dif(B, C).

您可能会找到一种更通用、更优雅的方式来描述包含 3 个以上元素的列表。不过,以上内容足以解决手头的任务。

因此,只需组合您已有的谓词,例如使用:

three_distinct_random_names(Ls) :-
        random_names(Ls),
        three_distinct_elements(Ls).

这只是您已经实现的条件的结合。总的来说,这个谓词的解决方案将为您提供您想要的:具有三个不同随机名称的列表。

但是,谓词也可能失败(练习:为什么?)。

要尝试谓词直到找到解决方案,请使用例如repeat/0:

?- repeat, three_distinct_random_names(Ls).

还有更好的方法来解决这个问题。然而,作为第一个近似值,我建议关注良好的构建 block ,描述您想要满足的条件。

我对你所写的内容有一个一般性评论:

I could write a new predicate for removing duplicates, but how would I substitute the duplicate with another variable then, so that the list still has three elements?

这一切的措辞都非常势在必行:您在这里想到的是“删除”、“替换”等。为了充分利用 Prolog,请重点描述条件对于您想要找到的解决方案,必须成立!

您想查找没有重复项的列表吗? 描述这样的列表必须是什么样子。你想要随机名字吗? 描述这个名字是什么样的,等等

关于prolog - 如何在序言中制作特定长度的随机列表而不重复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46512332/

相关文章:

当只存在一个时,Prolog 会尝试找到多个解决方案

sorting - 理解prolog中快速排序的运行轨迹

prolog - prolog 中的字符串操作

matrix - 为什么 "..."出现在我的 Prolog 矩阵答案中

list - 二叉树的广度优先 - 使用半上下文表示法

Prolog 最大术语大小

测试 "Safe term order"谓词

prolog - 如何以递归或任何其他方式打印所有可能的成绩?

具有动态谓词的模块

list - 具有多个相同元素的列表的排列Prolog