「テンパズル」は 4 桁の数字を 1 桁ずつに分解し、それに四則演算とカッコを使って 10 を作るパズルです。「メイク10」とか「切符番号の問題」と呼ばれることもあります。一般的なルールの場合、数字の順番を入れ替えてもよいのですが、数字を結合させることはできません。今回は 10 になる式だけではなく、いろいろな値で試してみましょう
それでは問題です。+, -, ×, ÷, ( ,) を使って、指定した値となる式を作ってください。すべての問題で符号 - を使うことは禁止します。
解法プログラムは「four fours」のプログラムを改造すれば簡単に作成することができます。説明は省略するので、詳細はプログラムリストをお読みください。
>>> solver0(10, 1, 2, 6, 9) (2 * (9 - 1)) - 6 = 10 6 - ((1 - 9) / 2) = 10 6 + ((9 - 1) / 2) = 10 ((9 - 1) / 2) + 6 = 10 ((9 - 1) * 2) - 6 = 10
>>> solver0(10, 1, 6, 1, 7) (6 / (1 + 1)) + 7 = 10 7 + (6 / (1 + 1)) = 10
>>> solver0(10, 8, 8, 8, 8) ((8 + 8) / 8) + 8 = 10 8 + ((8 + 8) / 8) = 10
>>> solver1(range(1, 11), 2, 3, 4, 5) ((2 - 3) * 4) + 5 = 1 ((2 * 3) + 4) / 5 = 2 (2 * (3 - 4)) + 5 = 3 (2 + 3) + (4 - 5) = 4 (2 * 3) + (4 - 5) = 5 2 + ((3 - 4) + 5) = 6 ((2 * 3) - 4) + 5 = 7 ((2 - 3) + 4) + 5 = 8 2 + ((3 * 4) - 5) = 9 ((2 * 3) - 4) * 5 = 10
>>> solver2(range(1, 20), 1, 4, 1, 5) (1 + 4) + (1 - 5) = 1 (1 - 4) + (1 * 5) = 2 ((1 - 4) + 1) + 5 = 3 ((1 - 1) * 5) + 4 = 4 ((1 - 1) * 4) + 5 = 5 ((1 + 1) * 5) - 4 = 6 (4 - (1 + 1)) + 5 = 7 ((1 * 4) - 1) + 5 = 8 1 + ((4 - 1) + 5) = 9 (1 + 4) + (1 * 5) = 10 (1 + 4) + (1 + 5) = 11 (1 - 4) * (1 - 5) = 12 ((1 + 1) * 4) + 5 = 13 ((1 + 1) * 5) + 4 = 14 ((1 * 4) - 1) * 5 = 15 1 + ((4 - 1) * 5) = 16 1 - (4 * (1 - 5)) = 17 (1 + 1) * (4 + 5) = 18 ((1 * 4) * 5) - 1 = 19 (1 + (4 - 1)) * 5 = 20
>>> solver2(range(1, 21), 2, 4, 1, 6) (2 + 4) + (1 - 6) = 1 (2 * 4) - (1 * 6) = 2 (2 - (4 + 1)) + 6 = 3 (2 - 4) + (1 * 6) = 4 ((2 - 4) + 1) + 6 = 5 ((2 + 1) * 4) - 6 = 6 ((2 * 6) - 1) - 4 = 7 ((2 * 1) * 6) - 4 = 8 ((2 / 4) + 1) * 6 = 9 (2 - 4) * (1 - 6) = 10 2 + ((4 - 1) + 6) = 11 (2 + 4) + (1 * 6) = 12 (2 + 4) + (1 + 6) = 13 (2 * 4) + (1 * 6) = 14 ((2 * 4) + 1) + 6 = 15 (2 * (4 + 1)) + 6 = 16 ((2 * 6) + 1) + 4 = 17 2 * ((4 - 1) + 6) = 18 (2 * (4 + 6)) - 1 = 19 2 + ((4 - 1) * 6) = 20
>>> solver2(range(1, 26), 2, 5, 1, 7) (2 + 5) + (1 - 7) = 1 ((2 * 5) - 1) - 7 = 2 (2 - (5 + 1)) + 7 = 3 (2 - 5) + (1 * 7) = 4 ((2 - 5) + 1) + 7 = 5 2 * ((1 - 5) + 7) = 6 2 / (1 - (5 / 7)) = 7 ((2 + 1) * 5) - 7 = 8 ((2 * 1) * 7) - 5 = 9 (2 * 7) + (1 - 5) = 10 (2 * (1 + 7)) - 5 = 11 ((2 - 1) * 5) + 7 = 12 2 + ((5 - 1) + 7) = 13 (2 + 5) + (1 * 7) = 14 (2 + 5) + (1 + 7) = 15 ((2 * 5) - 1) + 7 = 16 (2 * 5) + (1 * 7) = 17 ((2 * 5) + 1) + 7 = 18 (2 * (5 + 1)) + 7 = 19 ((2 * 7) + 1) + 5 = 20 (2 * (1 + 7)) + 5 = 21 2 * ((5 - 1) + 7) = 22 (2 * (5 + 7)) - 1 = 23 2 * (5 + (1 * 7)) = 24 (2 * (5 + 7)) + 1 = 25
>>> solver2(range(1, 31), 1, 2, 3, 4) (1 * 2) + (3 - 4) = 1 (1 + 2) + (3 - 4) = 2 ((1 * 2) - 3) + 4 = 3 1 + ((2 - 3) + 4) = 4 ((1 + 2) / 3) + 4 = 5 ((1 - 2) + 3) + 4 = 6 1 - ((2 - 4) * 3) = 7 ((1 - 2) + 3) * 4 = 8 ((1 * 2) + 3) + 4 = 9 (1 + 2) + (3 + 4) = 10 1 + ((2 * 3) + 4) = 11 1 + ((2 * 4) + 3) = 12 ((1 + 2) * 3) + 4 = 13 (1 * 2) + (3 * 4) = 14 (1 + 2) + (3 * 4) = 15 ((1 + 3) + 4) * 2 = 16 ((1 + 4) * 3) + 2 = 17 ((1 * 2) + 4) * 3 = 18 1 + ((2 + 4) * 3) = 19 ((1 * 2) + 3) * 4 = 20 1 + ((2 + 3) * 4) = 21 2 * ((3 * 4) - 1) = 22 ((2 * 3) * 4) - 1 = 23 ((1 + 2) + 3) * 4 = 24 1 + (2 * (3 * 4)) = 25
>>> solver2(range(1, 31), 1, 8, 2, 6) ((1 - 8) + 2) + 6 = 1 1 + (8 / (2 + 6)) = 2 (1 - (8 / 2)) + 6 = 3 (1 * 8) + (2 - 6) = 4 (1 + 8) + (2 - 6) = 5 1 + (8 - (6 / 2)) = 6 1 * ((8 + 6) / 2) = 7 1 + ((8 + 6) / 2) = 8 ((8 / 2) - 1) + 6 = 9 (1 * (8 / 2)) + 6 = 10 1 + ((8 / 2) + 6) = 11 ((1 * 8) - 2) + 6 = 12 1 + ((8 - 2) + 6) = 13 8 - ((1 - 2) * 6) = 14 ((8 - 1) + 2) + 6 = 15 ((1 * 8) + 2) + 6 = 16 (1 + 8) + (2 + 6) = 17 ((1 + 2) * 8) - 6 = 18 (8 - 1) + (2 * 6) = 19 (1 * 8) + (2 * 6) = 20 (1 + 8) + (2 * 6) = 21 ((1 * 8) * 2) + 6 = 22 1 + ((8 * 2) + 6) = 23 ((1 + 8) * 2) + 6 = 24 1 + ((8 / 2) * 6) = 25 ((1 + 2) * 6) + 8 = 26 ((1 + 8) / 2) * 6 = 27 (1 - 8) * (2 - 6) = 28 1 + ((8 + 6) * 2) = 29 (1 + (8 / 2)) * 6 = 30
>>>> solver3() 8 / (1 - (1 / 5)) = 10
一般的な規則で、値が 10 になる式が一つだけなのは 1, 1, 5, 8 の一通りです。
# # tenpuz.py : テンパズル (メイク10, 切符番号の問題) # # Copyright (C) 2022 Makoto Hiroi # from fractions import Fraction # 順列 def permutations(n, xs, m = 0, ys = []): if m == n: ps = xs[:m] return ys if ps in ys else ys + [ps] else: for i in range(m, len(xs)): xs[i], xs[m] = xs[m], xs[i] ys = permutations(n, xs, m + 1, ys) xs[i], xs[m] = xs[m], xs[i] return ys # 構文木 class Lf: def __init__(self, x): self.item = x class Nd: def __init__(self, x, l, r): self.op = x self.left = l self.right = r # 式の表示 def print_expr(expr, d): if isinstance(expr, Lf): print(expr.item, end='') else: if d > 0: print('(', end='') print_expr(expr.left, d + 1) print(f' {expr.op} ', end='') print_expr(expr.right, d + 1) if d > 0: print(')', end='') # 式の計算 def calc_expr(expr): if isinstance(expr, Lf): return expr.item else: l = calc_expr(expr.left) r = calc_expr(expr.right) op = expr.op if op == '+': return l + r elif op == '-': return l - r elif op == '*': return l * r else: return l / r # 四則演算 opls = ['+', '-', '*', '/'] # 式の生成 def make_expr(n, a, b, c, d): ans = [] for x in opls: for y in opls: for z in opls: for e in [Nd(x, Nd(y, a, b), Nd(z, c, d)), Nd(x, a, Nd(y, b, Nd(z, c, d))), Nd(x, Nd(y, Nd(z, a, b), c), d), Nd(x, a, Nd(y, Nd(z, b, c), d)), Nd(x, Nd(y, a, Nd(z, b, c)), d)]: try: r = calc_expr(e) if r.denominator == 1 and r.numerator == n: ans.append(e) except ZeroDivisionError: pass return ans # # 解法 # # 値が n となる数式を求める def solver0(n, a, b, c, d): for xs in permutations(4, [a, b, c, d]): ys = [Lf(Fraction(x, 1)) for x in xs] for e in make_expr(n, *ys): print_expr(e, 0) print(' =', n) # ns の中の値となる式を求める # 式は一つだけ出力する # 数字の並び替え禁止 def solver1(ns, a, b, c, d): xs = [Lf(Fraction(x, 1)) for x in [a, b, c, d]] for n in ns: es = make_expr(n, *xs) if es: print_expr(es[0], 0) print(' =', n) # ns の中の値となる式を求める # 式は一つだけ出力する def solver2(ns, a, b, c, d): for n in ns: for xs in permutations(4, [a, b, c, d]): ys = [Lf(Fraction(x, 1)) for x in xs] es = make_expr(n, *ys) if es: print_expr(es[0], 0) print(' =', n) break # 数値を桁に分解 def split_number(n, d): xs = [] for _ in range(d): xs.append(n % 10) n //= 10 return xs # リストを数値に変換 def to_number(xs): n = 0 for x in xs: n = n * 10 + x return n # 問題 10 の解法 def solver3(): table = [False] * 10000 for n in range(10000): if table[n]: continue xs = split_number(n, 4) es = [] for ys in permutations(4, xs): table[to_number(ys)] = True zs = [Lf(Fraction(y, 1)) for y in ys] es += make_expr(10, *zs) if len(es) == 1: print_expr(es[0], 0) print(' =', 10)