how to solve when the number of variables in the goal/query varies - Prolog Constrain Solver
这是使用 prolog 约束求解机制的经典 SENDMORY 密码算术问题解决方案的片段-
1 2 3 4 5 6 7 8 9 10 11 | :- lib(ic). sendmore(Digits) :- Digits = [S,E,N,D,M,O,R,Y], Digits :: [0..9], alldifferent(Digits), S #\\= 0, M #\\= 0, 1000*S + 100*E + 10*N + D + 1000*M + 100*O + 10*R + E #= 10000*M + 1000*O + 100*N + 10*E + Y, labeling(Digits). |
现在,要执行此操作,我将发送这样的目标/查询:
1 | ?- sendmore(Digits). |
这会给我返回数字的可能解决方案。
现在,我的问题是,我不想以这种方式对变量(如 S、E、N、...)进行"硬编码"排序,但目标/查询会给出变量。例如,如果我传递的查询类似于:
1 | ?- sendmore(S,E,N,D,M). |
然后,它应该只计算 SENDM 的值并假设其他变量不适用,因此将 0 分配给这些变量,然后继续计算。下次查询时,我可能会在查询中传递不同数量的变量.. 像 example:
1 | ?- sendmore(S,N,D,M,O,Y). |
程序应该同样计算。
我想要实现的是针对上述场景的更通用的问题解决器。任何关于这方面的指示都非常感谢。我对 prolog 很陌生,正在使用 ECLIPSE 约束求解器。
谢谢。
通常,目标中的变量和子句标题中的变量按位置匹配,而不是按名称匹配。所以调用
1 | sendmore0([S,E,N,D,M]) :- sendmore([S,E,N,D,M,_,_,_]). |
然而,这意味着您需要为每一种可能的组合实现这一点。
如果你真的想实现你所描述的,那么你需要给变量提供稳定的名字。在 ECLiPSe 中,您可以使用库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | :- lib(var_name). sendmore0(L) :- build_arg(["S","E","N","D","M',"O","R","Y"], L, A), sendmore(A). build_arg([], _, []) :- !. build_arg([H|T], L, [HA|HT]) :- match_arg(L, H, HA), build_arg(T, L, HT). match_arg([], _, _). % or use 0 as last argument if you want match_arg([H|T], Base, A) :- ( get_var_name(H, S), split_string(S,"#","",[Base,_]) -> A = H ; match_arg(T, Base, A) ). |
然后您可以使用较短的变量列表调用
1 2 3 4 | ?- set_var_name(S,"S"), set_var_name(E,"E"), sendmore0([S, E]). S = 9 E = 5 Yes (0.00s cpu, solution 1, maybe more) |
免责声明:这不是稳定名称的用途。它们用于调试目的。如果约阿希姆看到这个,他会在我的耳朵周围给我一个锋利的夹子...
这里有两个想法: