【问题标题】:Prolog - Lotto MachineProlog - 乐透机
【发布时间】:2015-03-10 15:14:55
【问题描述】:

这是我的第一篇文章。我一直在为一个大学项目自学 Prolog,我的任务是生成一个模拟乐透的程序,并将随机数(在本例中为 6)与用户拥有的数字进行比较。如果它们都匹配,那么您将被视为获胜者,如果不匹配,则返回“运气不好”。

到目前为止,我所能做的就是生成一个 1-50 范围内的随机数。之后我不知道该怎么做。

:- 使用模块(库(随机))。

?- 随机(1,50,Out)。

我知道我必须将随机数添加到列表中,但我不确定如何实现它。然后在数据库或事实库中有另一个数字列表(user_numbers)。然后使用 SWI-Prolog 检查它们是否相等。

对我来说,在 Prolog 中尝试和完成这是一个非常艰难的程序,尤其是在我自学的时候。如果有人能给我一些关于如何处理它的指示,我将不胜感激。

【问题讨论】:

  • 这对 Prolog 来说不是一个好的开始:random/3 有副作用。

标签: list random prolog rules


【解决方案1】:
pick_number(N) :- random(1, 50, N). 

我们需要选择一个包含 6 个数字的列表

lotto_numbers(Ns) :-
    length(Ns, 6),           % The length of our list is 6, now we have a list of 6 free variables.
    select_numbers(Ns).     % We need to select our numbers, binding them to our free variables. 

select_numbers([]).         % An empty list needs no picking
select_numbers([N|Ns]) :-
    pick_number(N),         % We pick the first number (bind the free variable to a random number)
    select_numbers(Ns).     % Then we pick the rest of the numbers.

我们需要检查持票人是否有中奖号码。数字的顺序是否重要?如果是这样,那么我们可以检查两个列表是否统一:LottoNumbers = LottoTicketNumbers。如果我们不关心顺序,那么我们需要一个稍微复杂一点的解决方案:

numbers_match([], []).          % if both lists are empty, then they must have all matched.
numbers_match([N|Ns], Ms) :-
    select(N, Ms, NewMs),       % remove N from Ms (if N matches an element in Ms), leaving NewMs
    numbers_match(Ns, NewMs).   % remove the rest of Ns from NewMs.

如果两个列表没有同时为空,那么它们并不完全匹配。 假设我们在数据库中有一些彩票,

lotto_ticket(Ns) :- lotto_numbers(Ns).

通过我们程序中的所有上述定义,我们可以生成一张乐透彩票,并生成一些乐透号码(实际上是相同的过程,但为了说明目的而命名不同),并查看它们是否具有所有且只有相同的号码:

  ?- lotto_ticket(T), lotto_numbers(L), numbers_match(T, L).
  false.

啊。我们输了也就不足为奇了……


这一切都很好,但是我们可以通过使用高阶来节省很多步骤 谓词和一些常用的库谓词:

alt_lotto_numbers(Ns) :-
    length(Ns, 6),
    maplist(random(1,50), Ns).  % `maplist/2` is just a way of calling a predicate on every member of a list.

alt_numbers_match(Ns, Ms) :-
    same_length(Ns, Ms),
    subset(Ns, Ms).

【讨论】:

  • 非常感谢一位病理学家。你这样给我回信真是太好了。可惜你不是我的教授。我仍然不明白你给我的答案的某些方面,可能是因为我对Prolog知之甚少,但在第一部分:pick_number(N) :- random(1, 50, N)。 lotto_numbers(Ns) :- 长度(Ns, 6), select_numbers(Ns)。选择号码([])。 select_numbers([N|Ns]) :-pick_number(N), select_numbers(Ns)。 % ?- ticket_numbers(TNs), lotto_numbers(LNs), TNs = LNs。我在 SWI 中运行它时不起作用
  • @JackNoone 我的代码可能有错误,这就是它不起作用的原因:但我并不完全清楚您要查询的内容以及“不起作用”的含义。您是否收到错误消息?单纯的“假”?还是您没有预料到的错误?
  • 我使用了您在上面发布的规则和事实,但是当我尝试通过询问程序是否彼此相等来运行它时,它返回:4 ?- ['/Users/JackNoone /Desktop/Prolog/lotto.pl']。 % /Users/JackNoone/Desktop/Prolog/lotto.pl 编译 0.00 秒,1 个子句为真。 5 ?- ticket_numbers(TNs), lotto_numbers(LNs), TNs = LNs。错误:顶层:未定义过程:ticket_numbers/1(DWIM 无法更正目标)
  • @JackNoone 啊!我懂了。抱歉,这是我的一些不清楚的结果:该查询只是作为我认为行不通的事情的一个例子。如果您查看我定义的谓词,您应该会看到,正如 swipl 告诉您的那样,谓词 ticket_numbers/1 没有在任何地方定义。这只是我为说明目的而编造的一个示例谓词。我编辑了我的答案以使事情更清楚。如果您有更多问题或其他问题,请告诉我 ;)
  • 谢谢,你很有帮助!只是为了帮助我更好地理解代码, Ms 是缩写吗?还有 lotto_ticket(T) 和 lotto_numbers(L),您是自己使用了 T 和 L,还是与某些东西相关联。很抱歉这些问题。他们可能在你看来很傻,但我绝对是一个试图自学的初学者。
猜你喜欢
  • 1970-01-01
  • 2021-07-09
  • 1970-01-01
  • 2012-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-31
  • 1970-01-01
相关资源
最近更新 更多