一个完整的解决方案超出了一个简单的 SO 问题的范围,但我可以勾勒出您需要的内容。
首先,为进位生成新字母:
0 T W O
0 T W O
+ Z Y X V
F O U R
然后您可以生成一个std::map<char, std::set<int>>
包含所有选项的。字母的标准范围是 {0..9},V 是 {0},Z 是 {1},Y 和 X 是 {0..1}。
接下来,您需要将添加的内容编码为一组子句。
enum class Op { Equal, SumMod10, SumDiv10, Even, Odd };
struct clause { Op op; std::vector<Var> children; };
std::vector<clause> clauses{
{Equal, { 'Z' , 'F'}},
{SumMod10, {'O', 'T', 'T', 'Y'}}, // O = (T+T+Y) mod 10
{SumMod10, {'U', 'W', 'W', 'X'}},
{SumMod10, {'R', 'O', 'O', 'V'}},
{SumDiv10, {'F', 'T', 'T', 'Y'}}, // F is the carry of T+T+Y
{SumDiv10, {'O', 'W', 'W', 'X'}},
{SumDiv10, {'U', 'O', 'O', 'V'}},
};
然后有趣的部分开始了:您需要创建一个计算,该计算将尝试使用它所拥有的知识来简化约束。例如,{SumMod10, {'U', 'O', 'O', 'V'}}
可以简化为{SumMod10, {'U', 'O', 'O', 0}}
since V=0
。有时子句可以缩小变量的范围,例如{Equal, {'Z', 'F'}}
约束可以立即将范围缩小F
到 {0,1}。
接下来,您需要教您的系统有关基本代数等式以进一步简化,例如:
{SumMod10, {A, 0, C}} === {SumMod10, {A, C, 0}} === {Equal, {A,C}}
甚至更抽象的东西,例如“如果 A >= 5 且 B >= 5 则 A+B >= 10”或“如果 A 是偶数B 是偶数,那么 A + B 也是偶数”。
最后,您的系统需要能够假设假设并反驳它们,或者证明一个假设无论如何都是正确的,就像您在帖子中所做的那样。例如,假设 R 是奇数就意味着 O + O 是奇数,这只有在 O 同时是奇数和偶数时才会发生。因此 R 必须是偶数。
最终,您将不仅实现了一个用于描述和评估数字域中的布尔子句的正式系统,您还将拥有一个目标驱动的解决方案引擎。如果这不仅仅是一种无聊的思考,我会强烈考虑采用 SMT 系统来为你解决这个问题,或者至少学习 Prolog 并在那里表达你的问题。