テンパズル(4つの数字で10を作るパズル)

プチ研究数論プチ研究

テンパズルとは、4つの数字を使って、10を作るパズルです。
このパズルの全問解答集をExcel VBAを使って作成してみました。

 

テンパズルの例

1,2,4,7の場合、
①\( 7+4-2+1=10 \)
②\( 7 \times 2 -4 \times 1 =10 \)
③\( 4 \times (7 \div 2 -1)=10 \)
などがあります。

是非下記からダウンロードして、眺めてみてください。↓↓

目次
  • 1. テンパズル 完成版
  • 2. ①4つの数字を全パターン用意する。
  • 3. ②式の形を一般化して作る。
  • 4. ③重複している式を削る
  • 5. ④①で作ったパターンを③の式にあてはめ、10になる式を探す。
  • 6. ⑤同じ式を削除する。
  • 7. ⑥÷0の削除
  • 8. ⑦痛恨の手作業
  • 9. ⑧反省点

テンパズル 完成版


ここからはどのようなプログラムを使って、この解答集を作ったのかを紹介します。
手順としては次の通り。
①4つの数字を全パターン用意する。
②式の形を一般化して作る。
③重複している式を削る。
④①で作ったパターンを③の式にあてはめ、10になる式を探す。
⑤同じ式を削除する。
⑥÷0を削除する。
⑦痛恨の手作業。
完成!!

簡単に書くと、こんな感じですが試行錯誤を繰り返して1か月以上考えましたね・・・。
論理的に薄かったり、無駄も多かったり・・・。能書きはこの辺にしておきましょう。
では、詳しく説明していきます。長いので、流し読みしてください。


①4つの数字を全パターン用意する。

まずは、テンパズルの問題となる4つの数字のパターンを全て作ります。
(1)まずはエクセル上のA列に、4桁の数字を1000~9999まで用意します。
これはエクセルの数値コピーを使えば一瞬ですね。

(2)MID関数を使って、CF列に4桁の数字を4つの数字に分解します。
MID関数とは、文字列の指定した位置から指定された文字数を表す関数です。

(3)C~F列を数値コピーして、HK列に貼り付けます。
これは、(4)のLARGE関数でエラーを防ぐためです。
このとき、文字列として、貼り付けられるため、警告マークから全て数値に
変換する必要があります。(ドラッグしてやれば、一発)

(4)LARGE関数を使って、MP列に4つの数字を大きい順に並び替えます。
  LARGE関数とは、データの中から指定した番目に大きい数値を表す関数です。

(1)~(4)までのエクセルの状況
1(1)~(4)

(5)並び替え機能を使って、各行をMP列の大きさにより並び替えます。
すると、例えば1001から出てきた1100と、1100から出てきた1100、1011から
出てきた1100、3つが重複してしまいます。

(6)Excel VBAを使って、4つの数字が重複している行を削除します。
これらを削除するために、次のようなマクロを組みます。
このマクロを何回か繰り返すことで、重複をなくすことができます。
1(6)(7)最後にL列に整理番号を付けて、4つの数字全パターンが重複なしでできあがります。
最初は1000~9999の9000の数字だったのが、重複をなくすと、
714通りになってしまいました。
一応、これに0000を付け加えて全715通りの数のパターンの完成です。
1(7)


②式の形を一般化して作る。

問題となる4つの数字は作り終えたので、今度は解答を出すための式作りに入ります。
(1)理論から考える。
4つの数字を\( a , b , c ,d \)とする。
四則の演算子(\( + , – , \times , \div ~\))の入れ方は、
\(~a\)と\(b\)の間で4通り、\(b\)と\(c\)の間で4通り、\(c\)と\(d\)の間で4通り、つまり\( 4^3=64 \)通り。

さらに、計算の順序を考える。左から順々に計算していくのを次のように表す。
a 1 b 2 c 3 d → 例:\( a + b + c + d \)
すると、今のも含めて全部で5通りの計算方法が得られる。
a 2 b 1 c 3 d → 例:\( (a+(b+c))+d \)
a 3 b 1 c 2 d → 例:\( a+((b+c)+d) \)
a 3 b 2 c 1 d → 例:\( a+(b+(c+d)) \)
a 1 b 3 c 2 d (a 2 b 3 c 1 d も同様) → 例:\( (a+b)+(c+d) \)

さらにさらに、4つの数字を並び替えることも考える必要があるため、4つの数字\( (a,b,c,d) \)の並べ方は
\(~ 4!=4\times3\times2\times1=24\)通り

以上より、1組の数字につき、\(64\times5\times24= \)7680通りの計算方法が考えられる。

(2)エクセル上に7680通りの計算方法を数字の代わりに\( a , b , c , d \)を使って作っていく。
まず、A列に0~7679までの通し番号、B列にN(0)~N(7679)までの配列を連続データの作成により、作る。
そして、C列、E列、I列、M列、Q列にそれぞれ\( = , a , b , c , d \)を入力する。

(3)最初に演算子を全て+で固定、さらに文字の順番も\( a,b,c,d \)で固定をして、カッコの位置を考える。
すると、カッコの位置は全文で5通りだったので、通し番号0~4は次のように式が書ける。

2(1)~(3)
(4)この5行をまとめて選択して、通し番号319までコピーをします。
そして、5行を1ブロックにして、演算子を変えていきます。(ここは地道に手作業・・)

(5)さらに、(4)で作った320行をまとめて選択して、通し番号7679までコピーをします。
そして、320行を1ブロックにして、Excelの置換機能で、文字の順番を入れ替えます。
(ここも地道に置換の設定をします。)
一応これで、全7680通りの計算式ができあがりました。
2(4)、(5)① 2(4)、(5)②


③重複している式を削る

あとは、①で作った全パターンを②で作った式に代入するだけなのですが、さすがに重すぎて(715題×7680通り=5491200回の計算)コンピュータが処理してくれません。そこで、\(a+b+c+d\)と\((a+b)+(c+d)\)のような、式的に等価なものを削って1つにまとめてしまいます。
(1)まず、②で作った式は、このままでは使い物にならないため、VBAのコピーします。
②でできるだけ簡単に式を作るために、セルを細かく分割してしまったので、単純にコピーはできません。
そこで、通し番号0~7679のBS列まで全てコピーをして、Wordに「テキストのみ保持」で貼り付けます。(それぞれの式を1行で表したいので、ページレイアウトでA3横に設定しておきましょう。)
そして、今ワードに貼り付けた式をまたコピーをし、Excel VBA内に貼り付けます。
すると、きれいにセルの境目が削除され、計算式としてふさわしい記述ができました。
3(1)① 3(1)②(2)今貼り付けた式を960個ずつに改行を使ってスペース的に分けます。(全部で8つに分かれる)
これは、1つのマクロ内で7680の式計算をこなそうとすると、オーバーフローして、処理が中断してしまうからです。(もしかしたら、最新のPCならできるのかもしれませんが・・・)

(3)8つに分けたそれぞれの前後に次のように記述する。

<以下VBAでの記述>

Sub テンパズル解答1()       ’最初のブロックなので、「1」
Dim a, b, c, d, e As Integer    ’変数a,b,c,d,eは整数型であるという宣言
a = Range(“C2").Value 'C2のセルの値をaに代入する。
b = Range(“C3").Value 'C3のセルの値をbに代入する。
c = Range(“C4").Value 'C4のセルの値をcに代入する。
d = Range(“C5").Value 'C5のセルの値をd代入する。
On Error Resume Next '÷0がでてきたら無視をする
Dim N(7679) As Single       'N(0)からN(7680)までの配列を宣言
————————————————-
N(0) = a + b + c + d '上の記述により、adが式に代入されて計算される。
N(1) = (a + (b + c)) + d
N(2) = a + ((b + c) + d)
N(3) = a + (b + (c + d))
N(4) = (a + b) + (c + d)
・・・・・・
N(959)= (a / c) / (b / d)
————————————————-
e = Range(“A1").Value 'A1のセルの値をeに代入する。
Dim x As Integer               '変数xは整数型であるという宣言
For x = 0 To 959             ’次の処理を960回繰り返しなさい。(x=0のとき↓)
Cells(9+x , e).Value = N(x) '9行目e列に入る値はN(0)の値
Next x
End Sub

Sub テンパズル解答2()            ’以下同様に
Dim a, b, c, d As Integer
a = Range(“C2").Value
b = Range(“C3").Value
c = Range(“C4").Value
d = Range(“C5").Value

Dim N(7679) As Single
On Error Resume Next

<以上VBAでの記述>

(4)さらに、次のようなマクロも記述する。
<以下VBAでの記述>

Sub テンパズル解答()
テンパズル解答1 '(3)で分割した1~8ブロックのプログラムを
テンパズル解答2         連続して行う。
テンパズル解答3
テンパズル解答4
テンパズル解答5
テンパズル解答6
テンパズル解答7
テンパズル解答8
End Sub

<以上VBAでの記述>

(5)下のようなA列、B列を記述したエクセルシートに、C2=1、C3=2、C4=3、C5=4をセルに入力して、
マクロ「テンパズル解答」を実行すると、次のような計算結果が表れる。
3(5)

例えば、C9からC13の10は、a=1 , b=2 , c=3 , d=4 を代入したときの、
N(0) = a + b + c + d
N(1) = (a + (b + c)) + d
N(2) = a + ((b + c) + d)
N(3) = a + (b + (c + d))
N(4) = (a + b) + (c + d)
の結果が表れている。

(6)ここで、重複している式を減らすための工夫を考える。
上に挙げたN(0)~N(4)の式のように明らかに等価なものから、
N(20) = a + b – c + d
N(29) = (a + b) – (c – d)
のように式変形をすると、等価になるものもある。
そこで、コンピュータに理論的に等価な式を見つけさせるのは難しいため、
いくつかの4つの数字の組を考え、答えが全て等しくなる式を重複しているものとみなし、
削除するという方法をとる。(100%排除できるわけではないが、ある程度は絞れる)
そこで、このシートのA1列の値を1増やして、さらにC2~C5の数字も違う数字にして、
マクロ「テンパズル解答」を実行した。
いくつかの4つの数字の組として用いたのは、全て同じ数や偶数だけ、奇数だけ、0が含まれる、無作為に抽出した数字など、次のような組である。↓
(1,2,3,4)、(4,4,4,4),(7,7,7,7),(2,4,6,8),(1,3,5,9),(3,3,4,7),(2,5,6,9),(6,6,7,9),(7,7,7,4),(4,4,4,5),(0,2,5,9),(1,4,6,8),(0,1,2,7)
その結果、次のようになった。
3(6)(7)これらの中から計算結果が全て等しいものを探るため、各式の13個の計算結果の合計(sum関数)、最大値(max関数)、最小値(min関数)、中央値(median関数)、さらにそれら4つの値の合計をとり、確実に同じ式かどうかを見やすくした。
3(7)(8)U列の値をもとに各行を並び替えて、合計、最大値、最小値、中央値が等しい式を削除した。
(ここでは、重複した式のある行を削除するマクロは①(6)と同じような仕組みです。)
3(8)

(9)これで重複している式をある程度削除できたため、もとの式番号通りに並び替えて、新たな番号をつけ、計算結果等の不要な列を削除することで、新たな式リストができた。
3(9)なんと、これで7680もあった式が、N(1102)までの1103個の式まで減らすことができた。
これならば、単純計算7倍のスピードで計算ができるだろう。


④①で作ったパターンを③の式にあてはめ、10になる式を探す。

③で作られた1103個の式に、①で作った715組の4つの数字を代入し、それぞれ10となる式を探します。
(1)A4,A104、A204と100間隔で1~715の番号を入力します。
さらに、B4~E4のセルにはvlookup関数を使って、
VLOOKUP($A4,問題!$L$4:$P$718,2)   (最後の2をセルによって変更する。)
と入力します。これにより、問題シートから、問題番号が1番なら、1番の問題(0、0、0、0)をB4~E4に4つの数字を並べることができます。
これまた、問題番号715(A71404)の行まで作ります。
4(1)
(2)次のようなマクロ「解答つくり」を記述します。
<以下VBAでの記述>

Sub 解答つくり()
Dim 問題番号 As Long
For 問題番号 = 1 To 715
 Dim a, b, c, d, e As Long
 a = Cells(問題番号 * 100 – 96, 2).Value
 b = Cells(問題番号 * 100 – 96, 3).Value
 c = Cells(問題番号 * 100 – 96, 4).Value
 d = Cells(問題番号 * 100 – 96, 5).Value

 Cells(問題番号 * 100 – 96, 6).Select
 On Error Resume Next
 Dim N(1102) As Single

 N(0) = a + b + c + d
 N(1) = a + b + c – d
 N(2) = a + b + c * d
 N(3) = (a + b + c) * d
 N(4) = a + ((b + c) * d)
 N(5) = a + b + c / d
 ・・・・・・・・
 N(1101) = d / ((c / a) – b)
 N(1102) = (d / c) / (a – b)

 For e = 0 To 1102
  If N(e) = 10 Then
    ActiveCell.Value = e
    ActiveCell.Offset(1, 0).Select
  End If
 Next e
Next 問題番号
End Sub
<以上 VBAでの記述>
これにより、F列に計算結果が10となる式のナンバーが全て挙がります。
そして、空白の行を削除し、式ナンバーがある行にも問題番号と問題を入力しておくと、次のようになります。
4(2)(3)F列の式ナンバーによる式がどのような式であったかを可視化したいので、G~V列に式ナンバーに対応する式を出力します。③(9)で作ったシートをvlookup関数で参照しています。一応、使った関数はコレ↓
IF($F4="","",VLOOKUP($F4,式参照!$C$8:$U$1110,4))
(式ナンバーが空欄なら、空欄のままにしなさい。そうでなければ、式ナンバーに対して対応する式を「式参照」のシートから読み込みなさい。)
4(3)(4)さすがに文字式のままだと見づらいので、XAM列に文字式を対応する数字に置き換えた式を作ります。
Y列、AC列、AG列、AK列は、次のように記述し、文字を数字にします。(例Y17)
=IF(F17="","",IF(H17="a",$B17,IF(H17="b",$C17,IF(H17="c",$D17,$E17))))
(式ナンバーが空欄であれば、空欄にしなさい。そうでなければ、H列がaのときはB列のaの値を、H列がbのときはC列のbの値を、H列がcのときはD列のcの値を、H列がdのときはE列のdの値を代入する)
それ以外のところはカッコや演算子をそのまま写せばよいので、(例X17)
=G17
で結構です。すると、次のようになります。
4(4)これで一応、各4つの数字の組で10になる式が出てきました。全部で約6000もの式が並びました。


⑤同じ式を削除する。

一応、④で答えは出そろいました。が、ちょっと無駄が多い気がします。下をご覧ください。(Excel2016になりました!)

5導入

なんと、同じ式が4つもあります!!
G~V列の式を見てみましょう。すると、上の4つの式の正体は以下のようになっています。
・式ナンバー4:a + ( ( b + c ) * d )
・式ナンバー151:a + ( ( b + d ) * c )
・式ナンバー434:b + ( ( a + c ) * d )
・式ナンバー733:c + ( ( a + b ) * d )
これらの式は明らかに等価ではありませんが、(a,b,c,d)=(2,2,2,2)のときは同じ意味になってしまうため、こんなにも無駄が出てしまうのです・・・。
ということで、⑤では、この現象を解消します。

(1)並び替えをして、同じような式が並ぶようにします。そのため、XAM列は関数での記述になっているので、全て値としてコピーをします。(AO列~BD列にコピーしました。)
そこで、「並び替え」機能を使用して、以下のように並び替えてもらいます。(A列の番号はそのままで、4つの数字の順番が同じものをくっつけるという戦法です)

5①

これでOKを押すと、こうなります↓
5①-2あ、式ナンバー521も同じような式でしたね(汗)
とりあえず、これで並べ替えが完了しました。

(2)次にまたまたif関数を使って、同じ式を抽出します。
以下の用にBF列に関数を入力します。なが~く書いていますが、要は「式ナンバー欄が空欄でない式のうち、上の式と比較して、同じなら"0″を、一部分でも違っていれば"1″を記入する」という指示です。

5②

あとは、①(6)で使った「重複式削除」のマクロを応用して、0となった行を削除します。

これで、全く同じ式は削除されました。


⑥÷0の削除

一見、完成したかのように思われましたが、おかしい行を発見!

6導入

4・0・0・0で10をつくる・・・。できませんよね。
それなのに、10ができている!!(10ができる場合、式ナンバーがF列にある)
式を見てみると、
式ナンバー87:4*0+0/0(つまり、\( 4\times0+0\div0~\))
0でわるという数学上の禁じ手を行っています。ここにきて、今までのマクロで書いてきた
On Error Resume Next '÷0がでてきたら無視をする
の影響に気づきました。
そこで、まずは÷0を見つけてその式を削除するということをしていきます。

(1)⑤と違って、今度は一行一行見ていきます。
BH列、BJ列、BL列を使って、AT列、AX列、BB列の数字が0の場合、÷0をしていないかを確認する関数をif関数で作ります。
ここで注意しなければならないのは、/(0+3)のようなパターンです。この場合であれば、式として問題でありません。よって、次のような関数をBH列に入力します。BH列では、4つの数字のうち、2番目の数字において、÷0をしていたら”0”を入力するようにしています。。(BJ列、BL列も同様に、3番目、4番目の数字を判定)

6①

(2)3つ並んだので、それらの数字を合計するSUM関数をBN列に作り、BP列には、IF関数で、BN列の値が3なら"1″、3以外なら"0″を入力するような関数とします。すると、上のような結果となります。
つまり、一つでも÷0があると、BN列は0になってしまいます。

(3)ここまで来れば、①(6)や⑤(2)で使用した「重複式削除」のマクロを応用して、0となった行を削除します。これで、÷0がなくなりました!!


⑦痛恨の手作業

ここまでエクセル関数とVBAに頼って、機械的にテンパズル解答集を作ってきました。最後の確認をしていたところ、思わぬところに伏兵がいました。それは次の行↓

7導入

\( 5+(0\div(6-6)) \)
\(~ (5+0)\div(6-6) \)
\(~ (5\div(6-6))+0 \)

・・・・そのパターンがあったか!! というこれまでの検査をかいくぐってきたエラー式の称賛と驚きの意を表すると共に、どうすればよいのか・・・と思い悩みました。

(1)そこで、とった方法は・・・手作業。
÷(○-△)の形で÷が入りうる列はAQ列とAV列(BA列にあったとしても、÷0はすでに⑥で削除しているため)。
そのため、その2列の"/"記号を"/“に置換して、見やすくすると、なんと該当した"/“記号は約1500個!
これならいける!!ということで、赤く染まった"/“の式を見ていきました。

そして、手作業による検閲をくぐり抜けた式たちがこちら↓

7完成

このファイルが テンパズル 完成版 からダウンロードできます!!どうぞご自由にお使いください。


⑧反省点

なんとなく気に入らないことが2点あります。
・⑦でやったことをプログラム化できなかったこと。複雑すぎて、能力が足りませんでした。
・「\(2\times 5+0+0 ~\)と\( 2\times 5-0-0 \)など式の本質は同じものを削除できなかったこと。

以上の点を解決できればもっと正確なものを、無駄なく作れると思います。
今後の課題ということにしておきましょう。


Fukuのコメント福助
中学の頃、数学の授業でテンパズルを毎時間やっていて、その魅力にはまりました。車のナンバーを見るたびにテンパズルをやっていたものです。何十、何百の問題を解いていくうち、中学生にして一つの予想が生まれました。
「テンパズルにおいて、4つの数字をたして7より小さい問題は10をつくることができない。」
この予想の証明。文字式など、いろいろ考えたもののできませんでしたが、大人になって、プログラミングを学び、この度証明することができました。
コンピュータを使って、数学の問題を解決するなんて、四色問題と一緒ですね。長い時間抱えてきた疑問が今、証明されました。■

プチ研究数論プチ研究

Posted by Fuku