2013-02-27 148 views
5

说你给出的隐窝算术拼图一个地穴的算术难题:解决关系数据库

SEND + MORE = MONEY

的目标是代替字母数字(0-9) ,这样才能解决问题。

我明白如何以数学方式处理该问题,但我不确定如何使用关系数据库解决此问题。

如何设计模式来解决这个问题?

SQL查询看起来会如何解决这个问题?

编辑: 有一些限制:

  1. 相同数量应该用于给定的信中,贯穿始终。例如,如果 对于字母E的猜测是“5”,那么E应该在其发生的所有位置得到值“5”。
  2. 不同字母应该得到不同的数字,例如,你不能将“4”既 E和以M.
  3. 数(字)
  4. 没有可能有任何前导零
+0

是否有单词长度的上限? – 2013-02-27 04:33:38

+0

一次只能解决一个难题,因此可以为该尝试专门创建/修改表格。拼图将全部为格式长度(4)+长度(4)=长度(5) – wilco 2013-02-27 04:41:15

+1

您的第一次编辑是不可能的,有超过10个不同的字母。每个都不能有自己的数字 – 2013-02-27 05:02:11

回答

4

笔者姿势两个不同的问题。

此答案可能参与

  • 有一个规定每个字符,其中每个字符不一定具有唯一的数字和超过10个字符所造成的问题,OVER + FLOW = STACK会收到一个唯一的数字,但对于OVER + FLOW + STACK来说这是不可能的,因为字母太多。

类似这样的东西可以工作,其中Digits表包含一列,其中earch记录包含1到9之间的整数(如果您愿意,则为0到9)。

交叉连接非常糟糕,性能明智,但这可能是一个起点。

select 
    top 5 
    O.num as O, 
    V.num as V, 
    E.num as E, 
    R.num as R, 
    F.num as F, 
    L.num as L, 
    W.num as W, 
    S.num as S, 
    T.num as T, 
    A.num as A, 
    C.num as C, 
    K.num as K, 
    (O.num * 1000 + V.num * 100 + E.num * 10 + R.num) as [OVER], 
    (F.num * 1000 + L.num * 100 + O.num * 10 + W.num) as FLOW, 
    (O.num * 1000 + V.num * 100 + E.num * 10 + R.num) + (F.num * 1000 + L.num * 100 + O.num * 10 + W.num) as OVER_plus_FLOW, 
    (S.num * 10000 + T.num * 1000 + A.num * 100 + C.num * 10 + K.num) as STACK 
from 
    Digits as O 
    cross join digits as V 
    cross join digits as E 
    cross join digits as R 
    cross join digits as F 
    cross join digits as L 
    cross join digits as W 
    cross join digits as S 
    cross join digits as T 
    cross join digits as A 
    cross join digits as C 
    cross join digits as K 
where 
    (O.num * 1000 + V.num * 100 + E.num * 10 + R.num) 
    + (F.num * 1000 + L.num * 100 + O.num * 10 + W.num) 
    = (S.num * 10000 + T.num * 1000 + A.num * 100 + C.num * 10 + K.num) 

根据我对问题的理解,有多种解决方案。这是第一个5这个代码中发现:

enter image description here

我删除了0,因为你可以用零替换每个字母,并得到一个便宜的答案(根据您最初的问题修订)。

这是唯一的表Digits

enter image description here

6

这回答用户提出的其他问题。

SEND + MORE = MONEY其中每个字符都有一个唯一的数字,没有字以零开始。

select 
    top 1 
    S.num as S, 
    E.num as E, 
    N.num as N, 
    D.num as D, 
    M.num as M, 
    O.num as O, 
    R.num as R, 
    Y.num as Y, 
    (S.num * 1000 + E.num * 100 + N.num * 10 + D.num) as [SEND], 
    (M.num * 1000 + O.num * 100 + R.num * 10 + E.num) as MORE, 
    (S.num * 1000 + E.num * 100 + N.num * 10 + D.num) + (M.num * 1000 + O.num * 100 + R.num * 10 + E.num) as SEND_plus_MORE, 
    (M.num * 10000 + O.num * 1000 + N.num * 100 + E.num * 10 + Y.num) as [MONEY] 

from 
    Digits as S 
    join digits as E on E.num <> S.num 
    join digits as N on N.num <> S.num and N.num <> E.num 
    join digits as D on D.num <> S.num and D.num <> E.num and D.num <> N.num 
    join digits as M on M.num <> S.num and M.num <> E.num and M.num <> N.num and M.num <> D.num 
    join digits as O on O.num <> S.num and O.num <> E.num and O.num <> N.num and O.num <> D.num and O.num <> M.num 
    join digits as R on R.num <> S.num and R.num <> E.num and R.num <> N.num and R.num <> D.num and R.num <> M.num and R.num <> O.num 
    join digits as Y on Y.num <> S.num and Y.num <> E.num and Y.num <> N.num and Y.num <> D.num and Y.num <> M.num and Y.num <> O.num and Y.num <> R.num 

where 
    (S.num * 1000 + E.num * 100 + N.num * 10 + D.num) 
    + (M.num * 1000 + O.num * 100 + R.num * 10 + E.num) 
    = (M.num * 10000 + O.num * 1000 + N.num * 100 + E.num * 10 + Y.num)  
    and S.num <> 0 and M.num <> 0 

我想过WHERE子句强制使用唯一的数字的东西,但我相信这最终处理之前太多排列WHERE子句检查。

因为我们只处理10位数字,我认为最好是建立长ON子句,而不是速度问题。

这里是没有疯狂的ON子句的FROM + WHERE子句。这在我的服务器上运行速度较慢。

from 
    Digits as S 
    cross join digits as E 
    cross join digits as N 
    cross join digits as D 
    cross join digits as M 
    cross join digits as O 
    cross join digits as R 
    cross join digits as Y 

where 
    (S.num * 1000 + E.num * 100 + N.num * 10 + D.num) 
    + (M.num * 1000 + O.num * 100 + R.num * 10 + E.num) 
    = (M.num * 10000 + O.num * 1000 + N.num * 100 + E.num * 10 + Y.num)  
    and S.num <> 0 and M.num <> 0 

     and (select max(B.Count) from 
       (select COUNT(*) as Count from 
        (select S.num, 's' as letter -- the letters are included to make sure the unions do not merge equivalent rows 
        UNION select E.num, 'e' 
        UNION select N.num, 'n' 
        UNION select D.num, 'd' 
        UNION select M.num, 'm' 
        UNION select O.num, 'o' 
        UNION select R.num, 'r' 
        UNION select Y.num, 'y') as A 
        group by A.num 
       ) as B 
      ) = 1