6、4、5、2、1の5つの数字に四則演算を挟んでどんな数字が作れるだろう?
もちろん頭を働かせて色々試すのも楽しい。 けれどプログラマーだったらサラッと全通り、出してみたくなりますよね?
数字は固定なので変数は四則演算四つの4箇所。 つまり可能な組み合わせは4の4乗。256通りの数字が作れます。
こういうときは Python を使うのが便利。 四則演算4つの組み合わせは以下でサクッと作れます:
itertools.product('+-*/' , repeat =4 )
リスト化してみるとこんな感じ(冒頭の10個):
>>> list(itertools.product('+-*/', repeat=4))[:10] [('+', '+', '+', '+'), ('+', '+', '+', '-'), ('+', '+', '+', '*'), ('+', '+', '+', '/'), ('+', '+', '-', '+'), ('+', '+', '-', '-'), ('+', '+', '-', '*'), ('+', '+', '-', '/'), ('+', '+', '*', '+'), ('+', '+', '*', '-')]
この各要素に数字を埋めこむ。これには zip でペアを作り、 itertools.chain.from_iterable でフラット化すればよい。(zip は短い側のリストに合わせられるので、末尾の 1 を後でくっつける)
(' ' .join (itertools.chain.from_iterable(zip('6452' , os))) + ' 1'
for os in itertools.product('+-*/' , repeat=4 ))
リストにして中身を見てみる(先頭から10個):
>>> list(' '.join(itertools.chain.from_iterable(zip('6452', os))) + ' 1' for os in itertools.product('+-*/', repeat=4))[:10] ['6 + 4 + 5 + 2 + 1', '6 + 4 + 5 + 2 - 1', '6 + 4 + 5 + 2 * 1', '6 + 4 + 5 + 2 / 1', '6 + 4 + 5 - 2 + 1', '6 + 4 + 5 - 2 - 1', '6 + 4 + 5 - 2 * 1', '6 + 4 + 5 - 2 / 1', '6 + 4 + 5 * 2 + 1', '6 + 4 + 5 * 2 - 1']
できあがった数式の値を知りたい。 こんな時に便利な組み込み関数 eval があるからこれを使う。(文字列を Python 式だと見て値を計算する)
>>> list((e, eval(e)) for e in (' '.join(itertools.chain.from_iterable(zip('6452', os))) + ' 1' for os in itertools.product('+-*/', repeat=4)))[:10] [('6 + 4 + 5 + 2 + 1', 18), ('6 + 4 + 5 + 2 - 1', 16), ('6 + 4 + 5 + 2 * 1', 17), ('6 + 4 + 5 + 2 / 1', 17.0), ('6 + 4 + 5 - 2 + 1', 14), ('6 + 4 + 5 - 2 - 1', 12), ('6 + 4 + 5 - 2 * 1', 13), ('6 + 4 + 5 - 2 / 1', 13.0), ('6 + 4 + 5 * 2 + 1', 21), ('6 + 4 + 5 * 2 - 1', 19)]
割り算が入ると小数点が出てくる。当然割りきれない式もある。 順序もバラバラなのでソートしたい。 割りきれない式を除外して並べ替えよう。
sorted(((e, eval (e)) for e in
(' ' .join(itertools.chain.from_iterable(zip('6452' , os))) + ' 1'
for os in itertools.product('+-*/' , repeat=4 ))
if eval (e) == int(eval (e))),
key = lambda p: p[1 ])
そして結果を文字列に整形するコードを追加:
'\n' .join(f'{e} = {int(v)}' for (e, v) in sorted(((e, eval (e)) for e in
(' ' .join(itertools.chain.from_iterable(zip('6452' , os))) + ' 1'
for os in itertools.product('+-*/' , repeat=4 ))
if eval (e) == int(eval (e))),
key = lambda p: p[1 ]))
ふむん……。 ざっと見た感じ、35日前からカウントダウン可能なようですね。
>>> print('\n'.join(f'{e} = {int(v)}' for (e, v) in sorted(((e, eval(e)) for e in ... (' '.join(itertools.chain.from_iterable(zip('6452', os))) + ' 1' ... for os in itertools.product('+-*/', repeat=4)) ... if eval(e) == int(eval(e))), ... key = lambda p: p[1]))) 6 - 4 * 5 * 2 - 1 = -35 6 - 4 * 5 * 2 * 1 = -34 6 - 4 * 5 * 2 / 1 = -34 6 - 4 * 5 * 2 + 1 = -33 6 - 4 * 5 - 2 - 1 = -17 6 - 4 * 5 - 2 * 1 = -16 6 - 4 * 5 - 2 / 1 = -16 6 - 4 * 5 - 2 + 1 = -15 6 - 4 * 5 + 2 - 1 = -13 6 - 4 * 5 + 2 * 1 = -12 6 - 4 * 5 + 2 / 1 = -12 6 - 4 * 5 + 2 + 1 = -11 6 - 4 - 5 * 2 - 1 = -9 6 - 4 - 5 * 2 * 1 = -8 6 - 4 - 5 * 2 / 1 = -8 6 - 4 - 5 * 2 + 1 = -7 6 - 4 - 5 - 2 - 1 = -6 6 - 4 - 5 - 2 * 1 = -5 6 - 4 - 5 - 2 / 1 = -5 6 - 4 * 5 / 2 - 1 = -5 6 - 4 - 5 - 2 + 1 = -4 6 - 4 * 5 / 2 * 1 = -4 6 - 4 * 5 / 2 / 1 = -4 6 - 4 * 5 / 2 + 1 = -3 6 - 4 - 5 + 2 - 1 = -2 6 / 4 - 5 / 2 - 1 = -2 6 + 4 - 5 * 2 - 1 = -1 6 - 4 - 5 + 2 * 1 = -1 6 - 4 - 5 + 2 / 1 = -1 6 / 4 - 5 / 2 * 1 = -1 6 / 4 - 5 / 2 / 1 = -1 6 + 4 - 5 * 2 * 1 = 0 6 + 4 - 5 * 2 / 1 = 0 6 - 4 - 5 + 2 + 1 = 0 6 / 4 - 5 / 2 + 1 = 0 6 + 4 - 5 * 2 + 1 = 1 6 + 4 - 5 - 2 - 1 = 2 6 + 4 - 5 - 2 * 1 = 3 6 + 4 - 5 - 2 / 1 = 3 6 / 4 + 5 / 2 - 1 = 3 6 + 4 - 5 - 2 + 1 = 4 6 - 4 + 5 - 2 - 1 = 4 6 / 4 + 5 / 2 * 1 = 4 6 / 4 + 5 / 2 / 1 = 4 6 - 4 + 5 - 2 * 1 = 5 6 - 4 + 5 - 2 / 1 = 5 6 / 4 + 5 / 2 + 1 = 5 6 + 4 - 5 + 2 - 1 = 6 6 - 4 + 5 - 2 + 1 = 6 6 + 4 - 5 + 2 * 1 = 7 6 + 4 - 5 + 2 / 1 = 7 6 + 4 - 5 + 2 + 1 = 8 6 - 4 + 5 + 2 - 1 = 8 6 - 4 + 5 + 2 * 1 = 9 6 - 4 + 5 + 2 / 1 = 9 6 - 4 + 5 + 2 + 1 = 10 6 - 4 + 5 * 2 - 1 = 11 6 + 4 + 5 - 2 - 1 = 12 6 - 4 + 5 * 2 * 1 = 12 6 - 4 + 5 * 2 / 1 = 12 6 + 4 + 5 - 2 * 1 = 13 6 + 4 + 5 - 2 / 1 = 13 6 - 4 + 5 * 2 + 1 = 13 6 * 4 - 5 * 2 - 1 = 13 6 + 4 + 5 - 2 + 1 = 14 6 * 4 - 5 * 2 * 1 = 14 6 * 4 - 5 * 2 / 1 = 14 6 / 4 * 5 * 2 - 1 = 14 6 + 4 * 5 / 2 - 1 = 15 6 * 4 - 5 * 2 + 1 = 15 6 / 4 * 5 * 2 * 1 = 15 6 / 4 * 5 * 2 / 1 = 15 6 + 4 + 5 + 2 - 1 = 16 6 + 4 * 5 / 2 * 1 = 16 6 + 4 * 5 / 2 / 1 = 16 6 * 4 - 5 - 2 - 1 = 16 6 / 4 * 5 * 2 + 1 = 16 6 + 4 + 5 + 2 * 1 = 17 6 + 4 + 5 + 2 / 1 = 17 6 + 4 * 5 / 2 + 1 = 17 6 * 4 - 5 - 2 * 1 = 17 6 * 4 - 5 - 2 / 1 = 17 6 + 4 + 5 + 2 + 1 = 18 6 * 4 - 5 - 2 + 1 = 18 6 + 4 + 5 * 2 - 1 = 19 6 + 4 + 5 * 2 * 1 = 20 6 + 4 + 5 * 2 / 1 = 20 6 * 4 - 5 + 2 - 1 = 20 6 + 4 + 5 * 2 + 1 = 21 6 * 4 - 5 + 2 * 1 = 21 6 * 4 - 5 + 2 / 1 = 21 6 * 4 - 5 + 2 + 1 = 22 6 + 4 * 5 - 2 - 1 = 23 6 + 4 * 5 - 2 * 1 = 24 6 + 4 * 5 - 2 / 1 = 24 6 + 4 * 5 - 2 + 1 = 25 6 * 4 + 5 - 2 - 1 = 26 6 + 4 * 5 + 2 - 1 = 27 6 * 4 + 5 - 2 * 1 = 27 6 * 4 + 5 - 2 / 1 = 27 6 + 4 * 5 + 2 * 1 = 28 6 + 4 * 5 + 2 / 1 = 28 6 * 4 + 5 - 2 + 1 = 28 6 + 4 * 5 + 2 + 1 = 29 6 * 4 + 5 + 2 - 1 = 30 6 * 4 + 5 + 2 * 1 = 31 6 * 4 + 5 + 2 / 1 = 31 6 * 4 + 5 + 2 + 1 = 32 6 * 4 + 5 * 2 - 1 = 33 6 * 4 + 5 * 2 * 1 = 34 6 * 4 + 5 * 2 / 1 = 34 6 * 4 + 5 * 2 + 1 = 35 6 + 4 * 5 * 2 - 1 = 45 6 + 4 * 5 * 2 * 1 = 46 6 + 4 * 5 * 2 / 1 = 46 6 + 4 * 5 * 2 + 1 = 47 6 * 4 * 5 / 2 - 1 = 59 6 * 4 * 5 / 2 * 1 = 60 6 * 4 * 5 / 2 / 1 = 60 6 * 4 * 5 / 2 + 1 = 61 6 * 4 * 5 - 2 - 1 = 117 6 * 4 * 5 - 2 * 1 = 118 6 * 4 * 5 - 2 / 1 = 118 6 * 4 * 5 - 2 + 1 = 119 6 * 4 * 5 + 2 - 1 = 121 6 * 4 * 5 + 2 * 1 = 122 6 * 4 * 5 + 2 / 1 = 122 6 * 4 * 5 + 2 + 1 = 123 6 * 4 * 5 * 2 - 1 = 239 6 * 4 * 5 * 2 * 1 = 240 6 * 4 * 5 * 2 / 1 = 240 6 * 4 * 5 * 2 + 1 = 241