SEND + MORE = MONEY
using System; using System.Collections.Generic; using System.Linq; class Program { static int ToInt(string s, int[] map) { int x = 0; foreach (var c in s) { x = 10 * x + map[c]; if (x == 0 && s.Length > 1) return -1; // leading zero } return x; } static void Solve_1(int p, char[] cs, int used, int[] map, string[] ss) { if (p == cs.Length) { var a = ss.Take(ss.Length - 1).Select(e => ToInt(e, map)); if (a.Contains(-1)) return; // 不正な変換結果 int b = ToInt(ss.Last(), map); if (a.Sum() == b) { Console.WriteLine("{0} = {1}", string.Join(" + ", ss.Take(ss.Length - 1)), ss.Last()); Console.WriteLine("{0} = {1}", string.Join(" + ", a), b); } return; } for (int i = 0; i < 10; i++) { if ((used & (1 << i)) != 0) continue; map[cs[p]] = i; // cs[p] に i を割り当てる Solve_1(p + 1, cs, used | (1 << i), map, ss); } } static void Solve(params string[] ss) { var cs = new HashSet<char>(ss.SelectMany(e => e)).ToArray(); if (cs.Length > 10) throw new Exception(); // 10 種類より多いと数字を割り当てられない var map = new int[128]; // どの文字にどの数字を割り当てたか Solve_1(0, cs, 0, map, ss); Console.WriteLine(); } static void Main() { Solve("SEND", "MORE", "MONEY"); Solve("CROSS", "ROADS", "DANGER"); Solve("SIX", "SEVEN", "SEVEN", "TWENTY"); } }
実行結果です。
$ time mono a.exe SEND + MORE = MONEY 9567 + 1085 = 10652 CROSS + ROADS = DANGER 96233 + 62513 = 158746 SIX + SEVEN + SEVEN = TWENTY 650 + 68782 + 68782 = 138214 mono a.exe 5.38s user 0.03s system 99% cpu 5.419 total