您好我遇到了这个谜题,这是一个名为Cryptarithms的着名的基于单词和数字的谜题的子集。假设您有一个表达式
S E N D + M O R E = M O N E Y
现在有趣的是,每个字母表代表一个0-9的唯一数字。我想编写一个广义求解器,但最后我写了一个粗暴的强制解决方案。任何接受者如何解决它?
我认为可以使用谓词逻辑或集合论来解决。我特别感兴趣的是找到基于C#或Python的解决方案。任何人。?
答案 0 :(得分:7)
今年的PyCon Raymond Hettinger在Python中讨论了AI编程,并介绍了Cryptarithms。
答案 1 :(得分:2)
这是一个小问题,蛮力解决方案并不是一个糟糕的方法。假设每个字母必须代表一个唯一的数字(即我们不允许解S = 9,M = 1,* = 0),我们看到要尝试的组合数是 n!,其中 n 是密码中唯一字母的数量。要评估的理论最大组合数是<10>! = 3 628 800 ,这对于计算机而言确实很小。
如果我们允许多个字母代表相同的数字,那么尝试的组合数量将受到 10 ^ n 的限制,其中 n 是唯一的数字字母。假设只有大写英文字母,我们有 10 ^ 26 的理论最大组合数,因此对于理论上最坏的情况,我们可能需要一些启发式方法。尽管如此,大多数实用的密码都少于26个独特的字母,因此正常情况可能会受到小于10的 n 的限制,这对于计算机来说也是非常合理的。
答案 2 :(得分:1)
好吧,试着把它写成一个函数列表:
SEND
MORE
----+
MONEY
如果我记得我的低年级数学,那应该是:
Y = (D+E) mod 10
E = ((N+R) + (D+E)/10) mod 10
...
答案 3 :(得分:1)
这是一种有效的强力方法,可以递归地循环遍历所有可能性,但也会记录特定问题的结构以简化问题。
每个方法的前几个参数代表每个分支的试验值,参数v1,v2等是尚未分配的值,可以在任何分配中传递 订购。该方法是有效的,因为它有最多8x7x5可能的试验解决方案,而不是蛮力的10!/ 2可能的解决方案
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void MESDYNR(int m, int s, int e, int d, int y, int n, int r, int v1, int v2, int v3)
{
// Solve for O in hundreds position
// "SEND" + "M?RE" = "M?NEY"
int carry = (10 * n + d + 10 * r + e) / 100;
int o = (10 + n - (e + carry))%10;
if ((v1 == o) || (v2 == o) || (v3 == o))
{
// check O is valid in thousands position
if (o == ((10 + (100 * e + 10 * n + d + 100 * o + 10 * r + e) / 1000 + m + s) % 10))
{
// "SEND" + "MORE" = "MONEY"
int send = 1000 * s + 100 * e + 10 * n + d;
int more = 1000 * m + 100 * o + 10 * r + e;
int money = 10000 * m + 1000 * o + 100 * n + 10 * e + y;
// Chck this solution
if ((send + more) == money)
{
Console.WriteLine(send + " + " + more + " = " + money);
}
}
}
}
static void MSEDYN(int m, int s, int e, int d, int y, int n, int v1, int v2, int v3, int v4)
{
// Solve for R
// "SEND" + "M*?E" = "M*NEY"
int carry = (d + e) / 10;
int r = (10 + e - (n + carry)) % 10;
if (v1 == r) MESDYNR(m, s, e, d, y, n, r, v2, v3, v4);
else if (v2 == r) MESDYNR(m, s, e, d, y, n, r, v1, v3, v4);
else if (v3 == r) MESDYNR(m, s, e, d, y, n, r, v1, v2, v4);
else if (v4 == r) MESDYNR(m, s, e, d, y, n, r, v1, v2, v3);
}
static void MSEDY(int m, int s, int e, int d, int y, int v1, int v2, int v3, int v4, int v5)
{
// Pick any value for N
MSEDYN(m, s, e, d, y, v1, v2, v3, v4, v5);
MSEDYN(m, s, e, d, y, v2, v1, v3, v4, v5);
MSEDYN(m, s, e, d, y, v3, v1, v2, v4, v5);
MSEDYN(m, s, e, d, y, v4, v1, v2, v3, v5);
MSEDYN(m, s, e, d, y, v5, v1, v2, v3, v4);
}
static void MSED(int m, int s, int e, int d, int v1, int v2, int v3, int v4, int v5, int v6)
{
// Solve for Y
// "SE*D" + "M**E" = "M**E?"
int y = (e + d) % 10;
if (v1 == y) MSEDY(m, s, e, d, y, v2, v3, v4, v5, v6);
else if (v2 == y) MSEDY(m, s, e, d, y, v1, v3, v4, v5, v6);
else if (v3 == y) MSEDY(m, s, e, d, y, v1, v2, v4, v5, v6);
else if (v4 == y) MSEDY(m, s, e, d, y, v1, v2, v3, v5, v6);
else if (v5 == y) MSEDY(m, s, e, d, y, v1, v2, v3, v4, v6);
else if (v6 == y) MSEDY(m, s, e, d, y, v1, v2, v3, v4, v5);
}
static void MSE(int m, int s, int e, int v1, int v2, int v3, int v4, int v5, int v6, int v7)
{
// "SE**" + "M**E" = "M**E*"
// Pick any value for D
MSED(m, s, e, v1, v2, v3, v4, v5, v6, v7);
MSED(m, s, e, v2, v1, v3, v4, v5, v6, v7);
MSED(m, s, e, v3, v1, v2, v4, v5, v6, v7);
MSED(m, s, e, v4, v1, v2, v3, v5, v6, v7);
MSED(m, s, e, v5, v1, v2, v3, v4, v6, v7);
MSED(m, s, e, v6, v1, v2, v3, v4, v5, v7);
MSED(m, s, e, v7, v1, v2, v3, v4, v5, v6);
}
static void MS(int m, int s, int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8)
{
// "S***" + "M***" = "M****"
// Pick any value for E
MSE(m, s, v1, v2, v3, v4, v5, v6, v7, v8);
MSE(m, s, v2, v1, v3, v4, v5, v6, v7, v8);
MSE(m, s, v3, v1, v2, v4, v5, v6, v7, v8);
MSE(m, s, v4, v1, v2, v3, v5, v6, v7, v8);
MSE(m, s, v5, v1, v2, v3, v4, v6, v7, v8);
MSE(m, s, v6, v1, v2, v3, v4, v5, v7, v8);
MSE(m, s, v7, v1, v2, v3, v4, v5, v6, v8);
MSE(m, s, v8, v1, v2, v3, v4, v5, v6, v7);
}
static void Main(string[] args)
{
// M must be 1
// S must be 8 or 9
DateTime Start = DateTime.Now;
MS(1, 8, 2, 3, 4, 5, 6, 7, 9, 0);
MS(1, 9, 2, 3, 4, 5, 6, 7, 8, 0);
Console.WriteLine((DateTime.Now-Start).Milliseconds);
return;
}
}
}
答案 4 :(得分:0)
this可能会有所帮助
编辑:您发布的wiki链接上的答案也很有用!