“SEND + MORE = MONEY”問題を解く


HaHaHa! - 覆面算汎用ソルバ より、覆面算クイズを解くコードを SqueakSmalltalk で。速度的にはまったく使い物にならないのですが、Haskell 版の汎用性(SEND + MORE = MONEY 専用ではない…)と、Shiro さんの Gauche 版 における文字列を介することにより得られる簡潔さ…の双方を意識してざっと書き下ろしてみました(肝心のソルバとしてのヒネリはまったくないです(^_^;))。

使い方

'SEND + MORE = MONEY' solve
'KYOTO + OSAKA = TOKYO' solve

定義

String >> solve
   | letters shouldntZeros |
   letters := self onlyLetters asSet asArray.
   shouldntZeros := self subStrings collect: [:str | str first] thenSelect: [:chr | chr isLetter].

   ($0 to: $9) reversed combinations: letters size atATimeDo: [:comb |
      comb permutationsDo: [:digits |
         (shouldntZeros noneSatisfy: [:shoudntZero | (digits at: (letters indexOf: shoudntZero)) = $0])
         ifTrue: [
            | expression |
            expression := self copy.
            letters with: digits do: [:letter :digit | expression replaceAll: letter with: digit].
            (Compiler evaluate: expression) ifTrue: [^ expression]]]].

   ^ false


答えが出るのに 1.2GHz PenM なノートで 10 分弱かかります(^_^;)。当然ですが、'SEND + MORE = MONEY' onlyLetters asSet size の大きさに依存します。 そーとー待たされましたが、とりあえず 'APPLE + GRAPE = CHERRY' を探してきてくれるところまでは確認しました。