【问题标题】:Prolog - How to generate a number with certain prerequisites?Prolog - 如何生成具有某些先决条件的数字?
【发布时间】:2018-03-19 01:45:55
【问题描述】:

所以我想创建一个简单的数字生成器,它生成一个介于 1 和 9 之间的数字,但它不允许成为提供的三个列表(数字列表)的一部分。一个例子:

findnumber(Number, [1,2,3], [3,4,5], [6,7,8]).
Number = 9.

或:

findnumber(Number, [1,2], [3,4], [5,6]).
Number = 7;
Number = 8;
Number = 9.

我会怎么做,我试过这个:

findnumber(Number, List1, List2, List3) :-
  random_between(1, 9, Number),
  not(member(Number, List1)),
  not(member(Number, List2)),
  not(member(Number, List3)).

我认为这会起作用,但显然不行,我认为这是因为 Number 是预先生成的,所以它无法真正找到先决条件。它只是检查它们是否不是成员,如果是,则谓词失败。

希望有人可以帮助我。 提前致谢。

【问题讨论】:

  • 它对我来说很好用...你如何测试它??
  • 当我运行它时,它失败了。但是当我输入这个时,我尝试了一些东西,现在它可以工作了,不知道我是否应该在这里给出答案。

标签: list random prolog numbers


【解决方案1】:

最近,在这个总体主题下进行了几次练习。这些任务迫使您将与逻辑关系的基本属性背道而驰的程序组合在一起:特别是,我们希望逻辑关系不依赖于隐式全局状态,例如随机数生成器的状态。这些是逻辑hacking的例子,而不是逻辑编程的例子。

无论如何,您的解决方案和分析都是完全有效的。

一个简单的方法是简单地反复尝试来生成这样的整数直到你最终成功。 Prolog 通过其内置的回溯机制使重复尝试变得容易。

您可以使用谓词repeat/0,它可以成功任意次数。因此,如果您只是在前面加上repeat/0 的调用,您的查询将完全按照预期工作:

?- 重复, findnumber(Number, [1,2], [3,4], [5,6])。 数字 = 9 ; 数字 = 9 ; 数字 = 8 ; 数字 = 8 ; 数字 = 7 。

您可以通过将整个查询包装在once/1 中来提交first 解决方案,即:

?- once((repeat, findnumber(Number, [1,2], [3,4], [5,6])))。 数字 = 7。

正如我所说,整个关系违反了我们对逻辑程序所期望的基本属性。例如,当再次发布完全相同的查询时,我得到了一个不同的答案

?- 一次((重复,findnumber(数字,[1,2],[3,4],[5,6])))。 数字 = 8。

这解释了为什么它对其中一位评论者“有效”(巧合)。

这些杂质使声明式调试和逻辑编程的许多其他好处不适用。我建议你选择一个不同的导师。请参阅,详细了解我们期望从逻辑关系中获得的属性,以及您如何在工作中从中受益。

【讨论】:

  • 感谢您的回答,如果将其视为介绍性练习,该练习到底有什么问题。我最近开始使用 prolog,我认为这是一个很好的尝试,可以暂时教我如何在 prolog 中编码。如果从纯逻辑的角度来看,您会建议教授什么样的入门练习?
  • 当你查询 Prolog 谓词时,问:有哪些解决方案?然后,当它报告一个解决方案时,您期望谓词也适用该具体解决方案。换句话说,当你查询?- p(X). 时,Prolog 用X 的一些绑定来回答,比如:X = t。那么,您当然希望?- p(t). 成立,对吧?在您的练习中,情况并非如此,因为谓词还取决于随机数生成器的某些隐式状态,并且在调用之间会发生变化!要以纯粹的方式解决这个问题,请明确随机数生成器的状态!
【解决方案2】:

您可以使用约束逻辑编程 (CLP) 轻松解决此类任务。例如,使用 Swi-Prolog,您可以使用以下代码来定义 findnumber

:- use_module(library(clpfd)).

findnumber(Number, List1, List2, List3) :-
    append([List1, List2, List3], NotIn),
    Number in 1..9,
    maplist(#\=(Number), NotIn),
    indomain(Number).

【讨论】:

    猜你喜欢
    • 2018-10-10
    • 1970-01-01
    • 2020-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-16
    • 1970-01-01
    相关资源
    最近更新 更多