👋

iPadを用いた数学の入学試験 (2)

2023/09/13に公開

前回のiPadを用いた数学の入学試験 (1)の続きです。この記事は2017年と2018年の記事をまとめたものです。ちょっと古いのですが,記録として残しておくため,2回に分けて報告します。

はじめに

城北高校の推薦入試の数学の試験では,『iPadをを用いて解く問題』を出題しています。今回は2回目となる平成30年1月の入試の報告です。

平成30年1月の推薦入試

平成30年1月22日に城北高校の推薦入試の数学の試験で次の問題を出題しました。
この問題はiPadを用いて解く問題です。

問題の作成過程で

これは,一般的に『8パズル』『スライドパズル』と呼ばれているもので,4\times 4から1枚除いた15枚の『15パズル』が有名です。このパズルで遊んだことのある人も多いのではないでしょうか。
配置を崩して,下の図のように順序だった配置に戻すパズルです。


(15パズル wikipediaより)

今回の問題は,

『特定の数字を入れ替えるときに,最小の移動の回数はどうなるのか?』

ということです。当初,動き方を局所的に考えて,その動きを組み合わせることによって,最小の移動の回数を求められるのではないかと考えていました。しかし,答えをチェックすると,『もっと回数を少なくできるんじゃない?』という指摘があり,実際にいろいろ動かしてみたところ,想定した回数よりも少ない移動で数字の入れ替えができることがわかりました。今までならば,その時点で入試問題としてはあきらめます。私たちの想定した規則には当てはまらなかったわけですから,模範解答すら危うい状態です。でも,『iPadもあるし,コンピュータもあるし,もう少し調べてみよう!』と思い,まずは『スライドパズル』について調べてみることにしました。

15パズル

wikipediaの中に『15パズル』についての説明がありました。

不可能な配置

このパズルの初期配置として有名な例に「目的の配置から14と15を入れ替えた状態」というものがある。一般化も可能だが、まずはこれを例として考える。

この説明から,

  • 例のように,14と15だけを入れ替えることは不可能である。
  • 空白の位置が同じであれば,移動は偶数回必要である。
  • 配置不可能なものがあり,どんな配置へも変形できるわけではない。

と理解しました。今回,私たちが作った問題では,2つの数字を入れ替える際に,\textbf{他の数字の配置はかわってもよい}のと,実際に移動できることは確認できているので,まあ,大丈夫かなあと考えました。

困難性

これにはちょっと参りました。配置Aから配置Bまで,仮に配置可能であったとすると,8パズルは31手以内でできるわけですが,その手順の求め方は単純ではないことが示唆されています。(NP困難と書いてあるし...)今回,2つの数字を交換する最小の移動の回数を調べるにあたり,

『その回数で最小であることが,本当にチェックできるのかなあ?』

と感じました。

コード検索

今回の問題では,『特定の数字を入れ替えるときに,最小の移動の回数はどうなるのか?』ということが知りたいので,特定の配置Aから配置Bまでの最短の手順を調べるコード(プログラム)などを作った人がいないかな?と考え,ネットを検索しました。すると,一番最初の正しい配置に変形するのに何手かかるか調べるコードは存在しました。(参考サイトの2番目)このプログラムをはじめ,15パズルに関するコードは様々ありました。しかし,それらのコードは

  • 特定の配置への最短経路を調べるものではない。
  • 『特定の2つ数字以外はどのような並びでもよい。』ということに対応できない。

ということがわかました。結局ネット上に,今回の要件を満たす適当なコードを見つけることはできませんでした。

コード作成

ネット上に利用できるコードはなかったので(探せなかっただけですが...),『自分でプログラムを書くしかない!』ということになったのです。ちょっと不安もありましたが,『こういうことはコンピュータの力を借りて,個人でもできる時代になったんだよな。』と思うことにして,フロー図を考えました。

数字の移動(交換)の仕組み

数字の位置を左図のように①から⑨とし,最初の配置を右図のようにします。(空白のところの数字は0としています。)

1回の移動で0と,どの場所の数字が交換されるのかを調べました。例えば,最初の配列で0は⑨の位置にあります。1回の移動で,⑥または⑧にある数字と0を交換することができます。

空白(0)の位置と交換できる位置をまとめると次のようになります。

  • 0が①のときは②,④と交換
  • 0が②のときは①,③,⑤と交換
  • 0が③のときは②,⑥と交換
  • 0が④のときは①,⑤,⑦と交換
  • 0が⑤のときは②,④,⑥,⑧と交換
  • 0が⑥のときは③,⑤,⑨と交換
  • 0が⑦のときは④,⑧と交換
  • 0が⑧のときは⑤,⑦,⑨と交換
  • 0が⑨のときは⑥,⑧と交換

記録と重複の削除

次に,繰り返しの手順を考えました。

(1) 0の位置を確認し,1回の移動で作られる配置を調べ,移動で得られた配置をリスト(データベース)に追加します。
(2) リストの中を調べ,重複があれば1つだけ残してあとは削除します。
(3) リストの中に求める2つの数字を入れ替えた配置がないか調べます。見つかればそれが求める最小の移動回数(答え)となります。見つからなければ,リストのそれぞれの配置の次の移動を考えます。

具体例

具体例を見てみます。

\bm{n=1} (1回目の移動)

(1) まず,bというリストを作ります。最初の配置を(1,2,3,4,5,6,7,8,0)とすると,

b=((1,2,3,4,5,6,7,8,0))

となります。
このリストに移動でできた新しい配置を追加していきます。

最初,0は⑨にあるので,⑥にある6,⑧にある8と交換可能です。

(1,2,3,4,5,0,7,8,6)

(1,2,3,4,5,6,7,0,8)

2つの配置をbに加えて,

b=((1,2,3,4,5,6,7,8,0),\\ (1,2,3,4,5,0,7,8,6),\\ (1,2,3,4,5,6,7,0,8))

となります。1回の移動によって,2パターン加わり,配置の数は3となります。

(2) このbの中に重複する配置はありません。

(3) 問題の(1)<3,\,5>,すなわち,③が5,⑤が3となっているものがあるか探します。今回はありません。((2),(3)も同様に探しますが,今回はありません。)

\bm{n=2} (2回目の移動)

(1) 2回目の移動ですが,最初の配置は検討しなくてもいいので,新しくできた2つの配列を考えます。

(1,2,\dot3,4,\dot5,0,7,8,\dot6)

は⑥の位置に0があるので,0は③にある3,⑤にある5,⑨にある6と交換可能です。
(1,2,0,4,5,3,7,8,6)

(1,2,3,4,0,5,7,8,6)

(1,2,3,4,5,6,7,8,0)

の3つの配置ができました。これらをbに加えます。
(1,2,3,4,\dot5,6,\dot7,0,\dot8)

は⑧の位置に0があるので,0は⑤にある5,⑦にある7,⑨にある8と交換可能です。
(1,2,3,4,0,6,7,5,8)

(1,2,3,4,5,6,0,7,8)

(1,2,3,4,5,6,7,8,0)

の3つの配置ができました。これらをbに加えます。

(2) いま,bは9個の配置となっていますが重複しています(下の波線部分)。

b=(\bm{(1,2,3,4,5,6,7,8,0)},\\ (1,2,3,4,5,0,7,8,6),\\ (1,2,3,4,5,6,7,0,8),\\ (1,2,0,4,5,3,7,8,6),\\ (1,2,3,4,0,5,7,8,6),\\ \bm{(1,2,3,4,5,6,7,8,0)},\\ (1,2,3,4,0,6,7,5,8),\\ (1,2,3,4,5,6,0,7,8),\\ \bm{(1,2,3,4,5,6,7,8,0)})

重複を除いて,bを7個の配置とします。

b=((1,2,3,4,5,6,7,8,0),\\ (1,2,3,4,5,0,7,8,6),\\ (1,2,3,4,5,6,7,0,8),\\ (1,2,0,4,5,3,7,8,6),\\ (1,2,3,4,0,5,7,8,6),\\ (1,2,3,4,0,6,7,5,8),\\ (1,2,3,4,5,6,0,7,8))

これで,2回以内の移動でできる配置のリストができました。

(3) 残念ながら,問題の(1)(2)(3)を満たす配置はまだありません。

このように調べていって,問題の(1)(2)(3)を満たす配置を調べることにしました。人間の手でやろうとすれば,樹形図的な広がりがあるので,すぐに厳しくなることは予想されます。また,『リストを調べ,重複があれば1つだけ残してあとは削除します。』と書きましたが,人間の手が行おうとすればとても大変な作業です。もちろん,コンピュータでやっても大変な作業で,もしかすると,途中で計算が終わらない可能性もありましたが,これはやってみなくてはわからないので,まず,この方針でコードを書くことにしました。

Mathematica

さて,実際にコードを書くわけですが,当初,『julia』,『Python』,『swift』のどれかで書こうと思っていました。ただ,私のコードのスキルでは,リストを並べ替えるだけで悩んでしまうので,今回は諦めました。今回選んだのは,『Mathematica』です。古くからある数式処理ソフトです。有償ですが,数学の関数は豊富に揃っています。かつて,利用した経験もありました。

まず,最初の配置をリストbに入れます。

b = {{1, 2, 3, 4, 5, 6, 7, 8, 0}}

次に0の位置によって,次の移動がどうなるかを考えて,リストに配置を追加する手続き関数Pを作りました。

P := Which[
  Position[b[[i]], 0][[1]][[1]] == 1,
    b = Append[b, {b[[i]][[2]],
      b[[i]][[1]],b[[i]][[3]],
      b[[i]][[4]],b[[i]][[5]],
      b[[i]][[6]],b[[i]][[7]],
      b[[i]][[8]],b[[i]][[9]]}];
    b = Append[b, {b[[i]][[4]],
      b[[i]][[2]],b[[i]][[3]],
      b[[i]][[1]],b[[i]][[5]],
      b[[i]][[6]],b[[i]][[7]],
      b[[i]][[8]],b[[i]][[9]]}],
  Position[b[[i]], 0][[1]][[1]] == 2,
    b = Append[b, {b[[i]][[2]],
      b[[i]][[1]],b[[i]][[3]],
      b[[i]][[4]],b[[i]][[5]],
      b[[i]][[6]],b[[i]][[7]],
      b[[i]][[8]],b[[i]][[9]]}];
    b = Append[b, {b[[i]][[1]],
      b[[i]][[3]],b[[i]][[2]],
      b[[i]][[4]],b[[i]][[5]],
      b[[i]][[6]],b[[i]][[7]],
      b[[i]][[8]],b[[i]][[9]]}];
    b = Append[b, {b[[i]][[1]],
      b[[i]][[5]],b[[i]][[3]],
      b[[i]][[4]],b[[i]][[2]],
      b[[i]][[6]],b[[i]][[7]],
      b[[i]][[8]],b[[i]][[9]]}],
  Position[b[[i]], 0][[1]][[1]] == 3,
    b = Append[b, {b[[i]][[1]],
      b[[i]][[3]],b[[i]][[2]],
      b[[i]][[4]],b[[i]][[5]],
      b[[i]][[6]],b[[i]][[7]],
      b[[i]][[8]],b[[i]][[9]]}];
    b = Append[b, {b[[i]][[1]],
      b[[i]][[2]],b[[i]][[6]],
      b[[i]][[4]],b[[i]][[5]],
      b[[i]][[3]],b[[i]][[7]],
      b[[i]][[8]],b[[i]][[9]]}],
  Position[b[[i]], 0][[1]][[1]] == 4,
    b = Append[b, {b[[i]][[4]],
      b[[i]][[2]],b[[i]][[3]],
      b[[i]][[1]],b[[i]][[5]],
      b[[i]][[6]],b[[i]][[7]],
      b[[i]][[8]],b[[i]][[9]]}];
    b = Append[b, {b[[i]][[1]],
      b[[i]][[2]],b[[i]][[3]],
      b[[i]][[5]],b[[i]][[4]],
      b[[i]][[6]],b[[i]][[7]],
      b[[i]][[8]],b[[i]][[9]]}];
    b = Append[b, {b[[i]][[1]],
      b[[i]][[2]],b[[i]][[3]],
      b[[i]][[7]],b[[i]][[5]],
      b[[i]][[6]],b[[i]][[4]],
      b[[i]][[8]],b[[i]][[9]]}],
  Position[b[[i]], 0][[1]][[1]] == 5,
    b = Append[b, {b[[i]][[1]],
      b[[i]][[5]],b[[i]][[3]],
      b[[i]][[4]],b[[i]][[2]],
      b[[i]][[6]],b[[i]][[7]],
      b[[i]][[8]],b[[i]][[9]]}];
    b = Append[b, {b[[i]][[1]],
      b[[i]][[2]],b[[i]][[3]],
      b[[i]][[5]],b[[i]][[4]],
      b[[i]][[6]],b[[i]][[7]],
      b[[i]][[8]],b[[i]][[9]]}];
    b = Append[b, {b[[i]][[1]],
      b[[i]][[2]],b[[i]][[3]],
      b[[i]][[4]],b[[i]][[6]],
      b[[i]][[5]],b[[i]][[7]],
      b[[i]][[8]],b[[i]][[9]]}];
    b = Append[b, {b[[i]][[1]],
      b[[i]][[2]],b[[i]][[3]],
      b[[i]][[4]],b[[i]][[8]],
      b[[i]][[6]],b[[i]][[7]],
      b[[i]][[5]],b[[i]][[9]]}],
  Position[b[[i]], 0][[1]][[1]] == 6,
    b = Append[b, {b[[i]][[1]],
      b[[i]][[2]],b[[i]][[6]],
      b[[i]][[4]],b[[i]][[5]],
      b[[i]][[3]],b[[i]][[7]],
      b[[i]][[8]],b[[i]][[9]]}];
    b = Append[b, {b[[i]][[1]],
      b[[i]][[2]],b[[i]][[3]],
      b[[i]][[4]],b[[i]][[6]],
      b[[i]][[5]],b[[i]][[7]],
      b[[i]][[8]],b[[i]][[9]]}];
    b = Append[b, {b[[i]][[1]],
      b[[i]][[2]],b[[i]][[3]],
      b[[i]][[4]],b[[i]][[5]],
      b[[i]][[9]],b[[i]][[7]],
      b[[i]][[8]],b[[i]][[6]]}],
  Position[b[[i]], 0][[1]][[1]] == 7,
    b = Append[b, {b[[i]][[1]],
      b[[i]][[2]],b[[i]][[3]],
      b[[i]][[7]],b[[i]][[5]],
      b[[i]][[6]],b[[i]][[4]],
      b[[i]][[8]], b[[i]][[9]]}];
    b = Append[b, {b[[i]][[1]],
      b[[i]][[2]],b[[i]][[3]],
      b[[i]][[4]],b[[i]][[5]],
      b[[i]][[6]],b[[i]][[8]],
      b[[i]][[7]],b[[i]][[9]]}],
  Position[b[[i]], 0][[1]][[1]] == 8,
    b = Append[b, {b[[i]][[1]],
      b[[i]][[2]],b[[i]][[3]],
      b[[i]][[4]],b[[i]][[8]],
      b[[i]][[6]],b[[i]][[7]],
      b[[i]][[5]],b[[i]][[9]]}];
    b = Append[b, {b[[i]][[1]],
      b[[i]][[2]],b[[i]][[3]],
      b[[i]][[4]],b[[i]][[5]],
      b[[i]][[6]],b[[i]][[8]],
      b[[i]][[7]],b[[i]][[9]]}];
    b = Append[b, {b[[i]][[1]],
      b[[i]][[2]],b[[i]][[3]],
      b[[i]][[4]],b[[i]][[5]],
      b[[i]][[6]],b[[i]][[7]],
      b[[i]][[9]],b[[i]][[8]]}],
  Position[b[[i]], 0][[1]][[1]] == 9,
    b = Append[b, {b[[i]][[1]],
      b[[i]][[2]],b[[i]][[3]],
      b[[i]][[4]],b[[i]][[5]],
      b[[i]][[9]],b[[i]][[7]],
      b[[i]][[8]],b[[i]][[6]]}];
    b = Append[b, {b[[i]][[1]],
      b[[i]][[2]],b[[i]][[3]],
      b[[i]][[4]],b[[i]][[5]],
      b[[i]][[6]],b[[i]][[7]],
      b[[i]][[9]],b[[i]][[8]]}]
  ]

追加されたPの中の重複を削除するときに,Mathematicaの『Union』という関数が使えます。Mathematicaを選んだ1番の理由のは,この関数があったことです。

リストbの中の重複を削除して,問題の3,5の入れ替え,1,5の入れ替え,3,6の入れ替えがあるか調べます。あれば,移動の回数をアウトプットします。なければ,次の移動に進みます。手作業でも15回以内で答えは見つかっていたので,繰り返す回数は15としました。

  Do[
    Do[P, {i, Length[b]}];
    b = Union[b];
    Do[
      If[
        b[[i]][[3]] == 5
        &&
        b[[i]][[5]] == 3,
        Print[k]],
        {i,Length[b]}],
    {k, 15}]

   Do[
    Do [P, {i, Length[b]}];
    b = Union[b];
    Do[
      If[
        b[[i]][[1]] == 5
        &&
        b[[i]][[5]] == 1,
        Print[k]],
        {i,Length[b]}],
    {k, 15}]

   Do[
    Do [P, {i, Length[b]}];
    b = Union[b];
    Do[
      If[
        b[[i]][[3]] == 6
        &&
        b[[i]][[6]] == 3,
        Print[k]],
        {i,Length[b]}],
    {k, 15}]

これらのコードはMacBook Proで実行しましたが,10秒かからずに結果が出ました。(実際に20回くらい繰り返すと数分待つ感じだったので,回数が多くなると,時短を考えなくてはならなかったようです。)

(Mathematicaのフロントエンド)

この結果から,新しくわかったこともあります。

(3)の答えは<3,6>=12(回)ですが,これは1通りしかありません。途中はわからないのですが,結果の形は1つしかないということです。実際にどのような並びかアウトプットしてみました。

In[15]:= Do[Do
          [P, {i, Length[b]}];
          b = Union[b];
          Do[If[b[[i]][[3]] == 6
              && b[[i]][[6]] == 3,
              Print[b[[i]]]],
               {i, Length[b]}], {k, 12}]

Out[15]:= {1,5,6,4,0,3,7,2,8}

この配置に必ずなるようです。

GeoGebra

これで,今回の問題の答えは確定しました。あとは,入試問題としてどのように出題するかです。この問題は数え上げを頭の中だけで行うのは困難が伴います。実際に動かして(スライドパズルを体験して)最小の移動回数を作業を通して求めてもらうのがよいのではないかと考えました。そのためには,実際にスライドパズルを用意する必要があります。本物を用意しても良かったのですが,iPadを利用した経験があったので,iPadの中にスライドパズルを用意することにしました。昨年の入試でGeoGebraを用いて立体図形の3Dモデルを作ったノウハウがあったので,スライドパズルもGeoGebraで作成することにしました。GeoGebraで公開されている教材の中でスライドパスルのコンテンツもあり,その作り方を参考にして,今回の入試用のものを作成しました。(参考サイト4番目)

(スライダーパズル 入試用にGeoGebraで作成)

動きなどを確認し,昨年と同様の手順で準備をしました。

おわりに

この問題は,昨年の立体図形の問題とは異なり,iPadのスライドパズルを利用しないと,答えを求めるのは非常に難しいです。(頭の中でパズルを動かして考えられる生徒もいるようですが...)
動かし方を組み合わせて計算でできる問題でもありません。それでも,この問題を出題したのは,このような問題にチャレンジしていってほしいというメッセージです。この出題は『数学の問題としては不適切なのではないか?』という指摘も想定しました。ご意見などいただけたら幸いです。いままでは難しいと考えられてきた,避けられてきた問題を,iPadなどのツールを用いることによって,考えたり,解決したり,答えを出したりできるのではと考えています。また,そういった教育を今後も展開していきたいです。

【推薦入試の答え】

(1) \bm{<3,5>=7}

(2) \bm{<1,5>=9}

(3) \bm{<3,6>=12}

【参考URL】

15パズル
https://ja.wikipedia.org/wiki/15パズル

15パズル自動解答プログラムの作り方
http://www.ic-net.or.jp/home/takaken/nt/slide/solve15.html

Mathematica
https://www.wolfram.com/mathematica/

スライドパズル(GeoGebra 参考サイト)
https://www.geogebra.org/m/b38dxFu2

スライドパズル(GeoGebra 入試用)
https://www.geogebra.org/m/CgABfuYE

Discussion