如果我们将两边都乘以(10*Y+Z)*Z,我们可以更改对(10*X+Y)/(10*Y+Z) = X/Z 的检查以避免除以零。因此,我们检查(10*X+Y)*Z = (10*Y+Z)*X。
使用 SWI Prolog 的 clp(fd) 库可以在给定的约束条件下生成所需的三元组:
:- 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]].