いきなりですが問題です.3×3の正方格子(下図)において,このうち4点を通る円は,いくつありますか.
元ネタは,算数授業研究125号*1のp.55です.「ちなみに答えは,5種類の円があわせて14個できる。」で,上段の文章を締めくくっています.
5種類の(半径が異なる)円を,確認していきましょう.まずは右左上4つの点を通る円です.細いグレーの線は,円の中心を求めるための作図です.
次は真ん中の点を中心として,その上下左右の点を通る円です.
真ん中の点を中心とする円は,もう一つあります.4隅の点を通ります.
少し,試行錯誤をすることで,次の円を見つけることができました.
4点を結ぶと長方形になります.長方形は,外接円を描くことができ,長方形の対角線の交点が円の中心,対角線が直径です.
長方形状より先に,ややトリッキーな4点の取り方に気づきました.円は次のとおりです.
中心は以下のとおりで,そこと4点との距離がみな等しいのが分かる線も入れました.
ここまで書いた5種類の円について,9つの点を区別する(回転や鏡像を同じとみなさない)ときの,円の総数を考えます.最初の描き方と同じ大きさは自身を含め4つあり,2番目と3番目は1つずつ,4番目と5番目は,円の中心がそれぞれ4通り考えられますので,円の数も4つずつです.ということで,4+1+1+4+4=14個ができました.
本当に,他にないでしょうか.これについては,総当たりで調べてみました.
描画と,4つの点を通る円の判定を行う,Rubyスクリプト(dotcircle.rb)を作成し,Gistに置きました.描画にはImageMagickのconvertコマンドを使用します.ruby dotcircle.rbを実行すると,上記のPNG画像を生成します.ruby dotcircle.rb 3を実行すると,4点を通る円の中心XY座標と半径rを出力しまして,具体的には以下のとおり,14通りです(下記以外にない,ということでもあります).
A(0,0) B(1,0) C(2,0) D(0,1) E(1,1) F(2,1) G(0,2) H(1,2) I(2,2) ABDE => x=0.500, y=0.500, r=0.707 ABFI => x=0.500, y=1.500, r=1.581 ABGH => x=0.500, y=1.000, r=1.118 ACDF => x=1.000, y=0.500, r=1.118 ACGI => x=1.000, y=1.000, r=1.414 ADHI => x=1.500, y=0.500, r=1.581 BCDG => x=1.500, y=1.500, r=1.581 BCEF => x=1.500, y=0.500, r=0.707 BCHI => x=1.500, y=1.000, r=1.118 BDFH => x=1.000, y=1.000, r=1.000 CFGH => x=0.500, y=0.500, r=1.581 DEGH => x=0.500, y=1.500, r=0.707 DFGI => x=1.000, y=1.500, r=1.118 EFHI => x=1.500, y=1.500, r=0.707
点のあいだの最小距離は1であり,rの値のうち,「0.707」は,「1.414」は,「1.118」は,「1.581」はを,それぞれ意味します.
プログラムは2つの独立したクラスで構成しています.描画に関するDotcircleDrawerクラスでは,愚直に座標を指定してconvertコマンドを作成し,呼び出す形をとりました.
判定処理を行うDotcircleCoordinateクラスについて,最もコーディングに時間を要したのは,任意個の座標(「要素数2の配列」の配列)を引数にとり,それらを全て通る円が一意に定まるかの判定です.同一直線上に3点がある場合などを取り除いてから,最初の3点を通る円の中心と半径を求め,残りの点について,中心からの距離が半径と等しいかを調べるという手順をとりました.垂直二等分線の方程式と,2元連立1次方程式の求解は,それぞれWebの情報を参考にし,URLを書きました.
このプログラムは,3×3の正方格子に限定することなく,任意の点の配置から,4点を通る円を全て見つけてくれます.ruby dotcircle.rb 4を実行すると,4×4の正方格子での算出を試みますが,実際に描くことのできる数よりもかなり多い種類を出力してしまっています.以下の円は,4×4の正方格子のうち8点を通るのですが,70個*2の異なる(4点を通る)円と判定しているのです.
*1:https://www.amazon.co.jp/dp/4491039429
*2:8C4=70です.