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