我想在某些游戏的prolog中计算所有三元组[X,Y,Z]的列表,挑战是
X,Y和Z是0到9之间的不同整数(包括两者),和 (10 * X + Y)/(10 * Y + Z)等于X / Z。
?- good_triples(L).
L = [[1, 6, 4], [1, 9, 5], [2, 6, 5], [4, 9, 8]].
像这样的事情,我开始编写代码,但如果有任何线索可以帮助,我不知道如何做到这一点:
good_list(L):- creat_triples([X,Y,Z],L).
creat_triples([X,Y,Z],L): X=< 9 ,Y=< 9 ,Z=< 0,
X>=0 , Y>=0,Z>=0,
答案 0 :(得分:2)
如果我们将两边乘以(10*X+Y)/(10*Y+Z) = X/Z
,我们可以更改(10*Y+Z)*Z
的支票,以避免除以零。因此,我们检查(10*X+Y)*Z = (10*Y+Z)*X
。
使用clp(fd)库为SWI Prolog提供了一种在给定约束条件下生成所需三元组的方法:
:- use_module(library(clpfd)).
create_tuple(L) :- % Expects create_tuple([X1,X2,...,Xn])
L ins 0..9,
all_distinct(L).
good_triple([X,Y,Z]) :-
create_tuple([X,Y,Z]),
(10*X+Y)*Z #= (10*Y+Z)*X,
label([X,Y,Z]).
如果你正在避开clp(fd)库,那么使用select/3
确保从域中选择的整数是不同的,你仍然可以更紧凑:
create_triple([X,Y,Z]) :-
select(X, [0,1,2,3,4,5,6,7,8,9], D1),
select(Y, D1, D2),
member(Z, D2).
good_triple([X,Y,Z]) :-
create_triple([X,Y,Z]),
(10*X+Y)*Z =:= (10*Y+Z)*X. % Check for numeric expression result equality with =:=
good_triple(L)
的查询产生:
?- good_triple(L).
L = [1, 6, 4] ;
L = [1, 9, 5] ;
L = [2, 6, 5] ;
L = [4, 9, 8] ;
false.
然后,正如Eugene所示,您可以使用setof
将解决方案收集到一个列表中:
good_triples(L) :-
setof(T, good_triple(T), L).
产量:
?- good_triples(L).
L = [[1, 6, 4], [1, 9, 5], [2, 6, 5], [4, 9, 8]].
答案 1 :(得分:1)
将您的需求直接转换为Prolog规则,而不进行任何可能的优化:
digits([0,1,2,3,4,5,6,7,8,9]).
good_triple([X,Y,Z]) :-
digits(D), % D is the list of digits
member(X,D), % X, Y and Z are members of D
member(Y,D),
member(Z,D),
X \=Y, % The numbers are all different
X \= Z,
Y \= Z,
Z \= 0, % Z can't be zero, since we are going to divide by it
Lhs is (10*X+Y)/(10*Y+Z), % Left hand side of the equation
Rhs is X/Z, % Right hand side of the equation
Lhs = Rhs. % The equation
现在收集所有结果:
setof(L, good_triple(L), R).
给出:
R = [[1, 6, 4], [1, 9, 5], [2, 6, 5], [4, 9, 8]]