覆面算
http://www16.atwiki.jp/tokoroten/pages/1211.html を見ていたら僕も書きたくなったので。
MacBookに10分くらい頑張ってもらって、ZERO + ZERO = ZERO から TEN + TEN == TWENTY までの全問題について総当たりをしたのだけども、結局あんまり面白い問題は見つからなかった。
答えのある問題だけ抜粋列挙しておくと:
Q: FOUR + FIVE = NINE num_answer: 72 Q: FOUR + FOUR = EIGHT num_answer: 56 Q: TWO + FIVE = SEVEN num_answer: 36 Q: ONE + FOUR = FIVE num_answer: 1200 Q: TWO + TWO = FOUR num_answer: 19 Q: ONE + ONE = TWO num_answer: 18
以下ソースコード。
# -*- coding: utf-8 -*- WORDS = """ZERO ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE TEN ELEVEN TWELVE THIRTEEN FOURTEEN FIFTEEN SIZTEEN SEVENTEEN EIGHTEEN NINETEEN TWENTY""".split() def compile_word(w): "e.g. ZERO => (((Z) * 10 + E) * 10 + R) * 10 + O" body = w[0] for c in w[1:]: body = "(%(body)s) * 10 + %(c)s" % locals() return body def perm(n, result): n -= 1 for i in range(10): if i not in result: if n > 0: for r in perm(n, result + [i]): yield r else: yield result + [i] def solve(v0, v1, sum_): print "Q: %s + %s = %s" % (v0, v1, sum_) if len(sum_) > max(len(v0), len(v1)) + 1: return # no answer if len(sum_) < max(len(v0), len(v1)): return # no answer used_chars = set((v0 + v1 + sum_)) if len(used_chars) > 10: return # unsolvable args = ", ".join(used_chars) body = "%s + %s == %s" % ( compile_word(v0), compile_word(v1), compile_word(sum_)) prod = eval("lambda %(args)s: %(body)s" % locals()) _to_str = lambda w: " + ".join("str(%s)" % c for c in w) to_str_body = "%s + ' + ' + %s + ' = ' + %s" % ( _to_str(v0), _to_str(v1), _to_str(sum_)) to_str_func = eval("lambda %(args)s: %(to_str_body)s" % locals()) num_answer = 0 for xs in perm(len(used_chars), []): if prod(*xs): print to_str_func(*xs) num_answer += 1 if num_answer: print "num_answer:", num_answer def main(): # for sum_ in range(10, -1, -1):# real 2m13.308s for sum_ in range(20, 10, -1):# real 7m20.159s for v0 in range(sum_ / 2 + 1): v1 = sum_ - v0 # 0 <= v0 <= v1 <= N solve(WORDS[v0], WORDS[v1], WORDS[sum_]) main()