Prolog - 乐透机

Prolog - Lotto Machine

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

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

:- use_module(library(random)).

?- random(1,50,Out).

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

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

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).