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).
这是我的第一个 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).