切符の番号で10を作る
切符の番号で10を作るパズル
4桁の数字を与えられたとき、4つの数字を一回ずつ使って(使用する
順序は問わない)10を作る。使える演算は加減乗除のみ。
例えば、
- 1234 --- 1+2+3+4 = 10
- 1234 --- 3*4-1*2 = 10
- 6789 --- (7+8)*6/9 = 10
- 6789 --- 8*(9-7)-6 = 10
- 6789 --- 6+8/(9-7) = 10
- 1199 --- (1+1/9)*9 = 10
のようにする。最後の「1199」は難問として有名な例である。
「3478」「1158」のような難問を解いて欲しい。
解法
4桁の数字を与えられたときにそれを用いて10になるような全ての
式を出力するようなプログラムを作ることを考える。
8-queenの場合と同様に、簡単な問題に還元することを考える。
すなわち、4つで10を作るのが難しいなら、3つで10を作る下請けを
作り、4つで10を作る関数は4つの数のうち2つを演算して全部で3つに
減らし、それを3つで10を作る関数に検討してもらうという作りにする。
例えば、
1, 2, 3, 4で10が出来るか?
という問題に対しては、
- (1,2を演算)
- 3(=1+2), 3, 4で10が出来るか?
- -1(=1-2), 3, 4で10が出来るか?
- 1(=2-1), 3, 4で10が出来るか?
- 2(=1*2), 3, 4で10が出来るか?
- 0.5(=1/2), 3, 4で10が出来るか?
- 2(=2/1), 3, 4で10が出来るか?
- (1,3を演算)
- 4(=1+3), 2, 4で10が出来るか?
- -2(=1-3), 3, 4で10が出来るか?
- 2(=3-1), 3, 4で10が出来るか?
- 3(=1*3), 2, 4で10が出来るか?
- 0.333...(=1/3), 2, 4で10が出来るか?
- 3(=3/1), 2, 4で10が出来るか?
- (1,4を演算)
- (2,4を演算)
- (3,4を演算)
というように分解する。
「3つで10を作る関数」は「2つで10を作る関数」を下請けとし、
「2つで10を作る関数」は「1つで10を作る関数」を下請けとする。
最後の「1つで10を作る関数」は、
渡された数が10であるか否か見るだけで良い。
高々4段の関数なので再帰を使わなくてもそれほど問題ではないが、
一応再帰を使って書くことにする。
最終結果を式で表示する必要があるので、各関数に渡す数字は、
数だけでなく「その数を計算する式」を文字列で持っていることにする。
例えば、上の例で言えば、
-
最初の「4つで10を作る関数」には(1, "1"), (2, "2"), (3, "3"), (4, "4")
が渡される。
-
「3つで10を作る関数」には(3, "(1+2)"), (3, "3"), (4, "4")
のようなものが渡される。
こうすれば、最後の「1つで10を作る関数」には、(10, "(((1+2)+3)+4)")の
ようなものが渡されるはずである。
この方針で作ったプログラムが、
make10.cである。
割り算が行われたときの精度の問題は、最後に10であるか判定するときに
充分10に近ければ10と見倣すと言う手抜きなプログラムである。
おまけとしてjavaで書いたプログラム
Make10.java
も付けておく。
余談
以下は、別のプログラムで調べた「10は作れて、自明解を含まない」数の
リストである。
ここで自明解とは、
- 加算・減算だけで出来ている。
- 与えられた数が0を含んでいる。
- 「×1」または「÷1」を含んでいる。
ものとした。上記262個は、比較的難しいものが多いといえる。
また、10以外の数を作る問題を考えると、「4444」は0〜9までの
全ての数が作れるということがよく知られている。
上で作ったプログラムで確かめてみると、10は作れないようだ。
では、0から始まって最も大きな数まで作れる4桁の数は何だろうか?
切符の番号で10を作る
/ kashi@mn.waseda.ac.jp