あと何日?

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

この記事が気に入ったらサポートをしてみませんか?