Prolog中的计算列表

时间:2014-12-18 01:35:46

标签: prolog

我想在某些游戏的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,

2 个答案:

答案 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]]