【问题标题】:Compute list in PrologProlog 中的计算列表
【发布时间】:2014-12-18 01:35:45
【问题描述】:

我想在某些游戏的序言中计算所有三元组 [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,

【问题讨论】:

    标签: prolog


    【解决方案1】:

    如果我们将两边都乘以(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]].
    

    【讨论】:

    • 3 个参数的问题仍然存在,我希望它只有一个。
    • @Nik,请参阅我的更新答案。它将像您在问题陈述中描述的那样工作:您只需查询 good_triples(L) 即可获得所有三元组。谓词头good_triple([X,Y,Z]) :-... 仅表示good_triple 有一个参数,它是一个由三个元素组成的列表,相当于定义good_triple(L) :- L = [X,Y,Z], ...。无论哪种方式,都需要提取XYZ 列表元素来进行计算。如果这不能满足您的需求,那么如果您可以更详细地解释您希望在问题陈述中看到的内容,则可以解决。
    • @Nik,关于我的回答还有其他问题吗?可以接受吗?
    • thnxx 绰绰有余
    【解决方案2】:

    将您的需求直接转换为 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]]
    

    【讨论】:

    • 我还是想用good_triples(L)这样的一个参数来做。
    • @Nik 它已经是一个参数,[X,Y,Z] 是一个列表,长度为 3。
    猜你喜欢
    • 1970-01-01
    • 2013-12-27
    • 1970-01-01
    • 1970-01-01
    • 2017-10-25
    • 1970-01-01
    • 1970-01-01
    • 2020-07-16
    • 1970-01-01
    相关资源
    最近更新 更多