为术语中的变量分配不同的数字

时间:2013-06-13 17:03:55

标签: prolog

我正在尝试创建一个谓词,它会生成一个带数字的复合词的所有可能的评估,例如: assign_distinct_values([A-B], E).应该会产生99个结果。

然而,我目前的努力中找不到不确定性:

assign_distinct_values(E, A) :-
       term_variables(E, V),
       assign_distinct_values(E, V, [0,1,2,3,4,5,6,7,8,9], A).

assign_distinct_values(E, [], [], E).
assign_distinct_values(E, [], _, E).
assign_distinct_values(E, V, N, A) :-
       select(Num, N, N2),
       select(Var, V, V2),
       Var is Num,
       assign_distinct_values(E, V2, N2, A).

生成对称结果,副本如:

  • 1-0
  • 0-1
  • 0-1
  • 1-0

2 个答案:

答案 0 :(得分:2)

L是值列表,E是输出变量

assign_distinct_values(E, A, L) :-
    member(E,L),
    delete(L,E,L1),
    member(A,L1).

使用prolog谓词要快得多。 member(X,L)检查X是否在L中,如果是,我们创建一个新的列表L1,不包含带有delete(L,X,L1)的X,并再次以相同的方式检查第二个成员。

另一个版本:

assign_distinct_values(E, A) :-
    L = [0,1,2,3,4,5,6,7,8,9],
    member(E,L),
    delete(L,E,L1),
    member(A,L1).

有用吗?我的机器上没有安装prolog。

此致

答案 1 :(得分:2)

首先考虑使用更有意义的命名约定:我建议在表示列表的变量名称后附加一个“s”,并更系统地对它们进行编号(从0开始),并使用更具说明性和意义的谓词名称: / p>

with_distinct_integers(E0, E) :-
       term_variables(E0, Vs),
       with_distinct_integers(E0, Vs, [0,1,2,3,4,5,6,7,8,9], E).

with_distinct_integers(E, [], [], E).
with_distinct_integers(E, [], _, E).
with_distinct_integers(E0, Vs0, Ns0, E) :-
       select(Num, Ns0, Ns),
       select(Var, Vs0, Vs),
       Var is Num,
       with_distinct_integers(E0, Vs, Ns, E).

现在关注with_distinct_integers/4。您会看到第一个子句被第二个子句包含在内,因此您可以省略第一个子句而不会丢失解决方案。变量Var仅用于将其与Num统一,因此您可以立即使用单个变量:

with_distinct_integers(E, [], _, E).
with_distinct_integers(E0, Vs0, Ns0, E) :-
       select(Num, Ns0, Ns),
       select(Num, Vs0, Vs),
       with_distinct_integers(E0, Vs, Ns, E).

您仍然会发现这个简化版本的非预期重复解决方案,我将其作为一个简单的练习,以找出导致此问题的原因:

?- with_distinct_integers(X-Y, [X,Y], [0,1], A).
..., A = 0-1 ;
..., A = 1-0 ;
..., A = 1-0 ;
..., A = 0-1 ;
false.

提示:只是在声明上明确了简化定义。继续简化:当你已经拥有所需的一切,即它的变量可用时,为什么要绕过原始术语?考虑:

with_distinct_integers(E) :-
       term_variables(E, Vs),
       numlist(0, 9, Ns),
       with_distinct_integers(Vs, Ns).

with_distinct_integers([], _).
with_distinct_integers([V|Vs], Ns0) :-
       select(V, Ns0, Ns),
       with_distinct_integers(Vs, Ns).

查询示例,计算所有解决方案:

?- findall(., with_distinct_integers([X-Y]), Ls), length(Ls, L).
Ls = ['.', '.', '.', '.', '.', '.', '.', '.', '.'|...],
L = 90.

方面的惊喜:只有90个解决方案,而不是99个。

还要考虑使用有限域约束,它是整数关系,可以让你轻松地制定这样的任务:

:- use_module(library(clpfd)).

with_distinct_integers(E) :-
        term_variables(E, Vs),
        Vs ins 0..9,
        all_different(Vs),
        label(Vs).

示例查询:

?- with_distinct_integers(X-Y).
X = 0,
Y = 1 ;
X = 0,
Y = 2 ;
X = 0,
Y = 3 .