我正在尝试编写一个谓词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
以合理的方式表达术语的不平等(参见 prolog-dif ):
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/