2013-02-27 184 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