无零数字数学谜题:用Prolog/CLP(FD)查找符合要求的运算公式
存在这类符合要求的公式,也完全可以用Prolog + CLP(FD)实现批量搜索
首先给几个简单的符合要求的例子,公式本身无0,结果包含1-9所有数字:
- 基础款:
987654321本身就满足要求,不需要额外运算 - 简单运算款:
123456789 * 2,计算结果为246913578,刚好覆盖1-9所有数字无重复,公式内所有字面量均不含0 - 无序结果款:
91827364 * 1 + 5,计算结果为918273645,数字顺序打乱但包含全部1-9数字,公式无0
用Prolog/CLP(FD)搜索的实现思路
我们只需要把需求拆解为两个约束条件,交给CLP(FD)的约束求解器处理即可:
- 公式内所有字面数字的每一位都不能出现0
- 公式的计算结果是9位数,每一位恰好是1-9各出现一次,无重复无0
核心谓词示例
首先实现判断数字是否不含0的谓词:
no_zero(0) :- !, false. no_zero(N) :- N mod 10 #\= 0, Next #= N // 10, (Next = 0 ; no_zero(Next)).
然后实现判断结果为1-9全排列的谓词:
% 拆分数字为各位的列表 digits(0, []). digits(N, [D|Ds]) :- N #> 0, D #= N mod 10, Next #= N // 10, digits(Next, Ds). pandigital_1_to_9(Res) :- Res in 123456789..987654321, digits(Res, Ds), length(Ds, 9), all_distinct(Ds), maplist(#\=(0), Ds).
如果我们只需要搜索二元运算的符合要求的公式,比如A * B结构,只需要加如下查询即可:
?- A in 1..9999, B in 1..9999, no_zero(A), no_zero(B), Res #= A * B, pandigital_1_to_9(Res), label([A,B]).
运行后就能批量得到所有符合要求的二元乘法公式,比如前面提到的123456789 * 2就会被搜索出来。
如果需要支持更复杂的公式结构(比如加减乘除嵌套、幂运算、阶乘等),只需要扩展公式生成的逻辑,给所有字面量加上no_zero约束,输出结果加上pandigital_1_to_9约束即可,只是公式结构越复杂,搜索空间越大,需要按需加剪枝规则优化搜索速度。
内容的提问来源于stack exchange,提问作者user502187
相关产品推荐
相关产品推荐

