sasaharayuugo.net

ジュニア算数オリンピック 二次元上のユークリッド幾何の問題 その13

【随時更新】ユークリッド幾何学の定理や作図まとめ - ニート歴10年からの数学日記 を機械的に適用して、解答に至れるかを探る。今はこの自分で書いたプログラムを使っている。考察はユークリッド幾何学の原理についてのメモ - ニート歴10年からの数学日記ジュニア算数オリンピック04年度ファイナル問題6 辺の和について、三角形の検出について - ニート歴10年からの数学日記
 

 

06年度トライアル問題 問題9

『図の四角形ABCDはAB=BC=CDで、角B=168度、角C=108度です。角Dの大きさを求めなさい。


昨日の続きで、2ステップ目。気が済むまでこの問題をやり続けることにする。

初期設定

triangle_lst = {}

    angle_equ = {
        168 : 0,
        "ABC" : 0,
        108 : 1,
        "BCD" : 1
    }

    side_equ = {
        "AB" : 0,
        "BC" : 0,
        "CD" : 0
    }

    sum_angle_lst = [ ]

    sum_side_lst = [ ]
    
    角
    0 : [168, 'ABC']
    1 : [108, 'BCD']

    角の和

    辺
    0 : ['AB', 'BC', 'CD']

    辺の和

    三角形

作図

以下5種類の作図をしていく。直接作図したもの以外に三角形や、あるいは正四角形や正五角形ができていたら、次の定理ループで角度が明らかになる可能性がある。


今回は2ステップなので、1ステップ目では判断せず、2ステップ目で判断する。


まず1ステップ目として、点と点を結んで線にする。それぞれの点に着目し、繋がってない点は全て選択肢になる。
今回はAとC、BとDがあり得る。

まず1ステップ目として、AとCを繋げる作図をする。ちょっと試しに、プログラムだったらどうなるかやってみるかな。完全にpythonでは無く、イメージで。

A_angle = [
        [B, ?, D, ?]
    ]

    A_distance = [
        B : AB,
        D : AD
    ]

    B_angle = [
        [C, 168, A, ?]
    ]

    B_distance = [
        C : BC,
        A : AB
    ]

    C_angle = [
        [D, 108, B, ?]
    ]

    C_distance = [
        D : CD,
        B : BC
    ]

    D_angle = [
        [A, ?, C, ?]
    ]

    D_distance = [
        A : AD,
        C : CD
    ]

注目すべきは角度だろう。

A_angle = [
        [B, ?, D, ?]
    ]

    B_angle = [
        [C, 168, A, ?]
    ]

    C_angle = [
        [D, 108, B, ?]
    ]

    D_angle = [
        [A, ?, C, ?]
    ]

              [B, ?, D, ?]
          [C, 168, A, ?]
      [D, 108, B, ?]
   [A, ?, C, ?]
[B, ?, D, ?]

こういうイメージになるんだろうか。最後に進む方向である、BとDの間にCとの線が入ることになる?で、交点は分かる分だけ。

[B, ?, D, ?]
   [A, ?, C, ?]
      [D, 108, B, ?]
          [C, 168, A, ?]
              [B, ?, D, ?]

いや、そうですら無いんだよな。歪んだ図形なんていくらでもあり得るから、クラスタでは分からない。

四角形の場合は、BとかDの角度が180°を超えたら、その180°を超えた側の外で繋がるんだろうか。

ただ、根本的に角度が分からない場合があるわけで、その場合はどこの間に入るか分からない。
それを基本に考えて、連続していると分かった分だけ別の所に記述するのが正しいのかもしれない、もしかしたら。

(休憩を挟んで分かったが、あの角度のリストは循環リストのつもりで、2つの関係なら、右にも左にも展開できる。つまりクラスタの方向?すら本当は分からない。ただクラスタだということが分かるだけで)


単純に考えると、こうなるだろうな。

A_angle = [
        BAD : ?
    ]

    A_distance = [
        B : AB,
        D : AD
    ]

    B_angle = [
        ABC : 168
    ]

    B_distance = [
        C : BC,
        A : AB
    ]

    C_angle = [
        BCD : 108
    ]

    C_distance = [
        D : CD,
        B : BC
    ]

    D_angle = [
        ADC : ?
    ]

    D_distance = [
        A : AD,
        C : CD
    ]

いやそうじゃなくて、何と何が繋がっているかを管理しておけば、それで良いんじゃないかな。あまりにも重複しているというか。

A_connect = [B, D]

    B_connect = [A, C]

    C_connect = [B, D]

    D_connect = [A, C]

それで、分かった角や辺だけ文字列にして登録していくような。角や辺の足し算のリストの他に、連続している角や辺の足し算を記述するためのリストが必要かもしれないな。いや、BACとCADがあれば、必ずBADか?分からん。


triangle_lst、angle_equ、side_equ、sum_angle_lst、sum_side_lst、の5つの生成を自動化できるような構造を探せばそれで良い。
休憩を挟んで考えてみたんだが、そうすると基本的にはこうなるだろう。

W_connect = [
        [[X], [Y]]
    ]

    X_connect = [
        [[W, Y], []],
        [[Z], []]
    ]

    Y_connect = [
        [[W, X], []],
        [[Z], []]
    ]

    Z_connect = [
        [[X], []],
        [[Y], []]
    ]

つまり、一直線上にあるものは、「[[近い順に0から], [反対側も近い順から]]」、という風に記述すると良いのではないか。
そうすると、triangle_lst、平行線関係以外はangle_equ、定義を入れるだけなのでside_equ、sum_side_lstは自動化できる。
問題は、angle_equの平行線関係、後はsum_angle_lstで角が二種類できて、180°以下がどちらか分からないという事じゃないか。


angle_equの平行線関係は、平行線を別に登録してしまえば良いのではないか。例えば展開するとして、[A, B, C, D, E]と[F, G, H, I]という具合に。
Aを調べて例えばGと繋がっていたら、登録するというような処理にする。
その時に、その2つの平行線の関係における方向のようなものがあって、それは揃える必要がある。
例えば人間の普通の見え方で、[A, B, C, D, E]と[F, G, H, I]の方向が揃っていれば、AからGに繋がった時に、更にその先の点とリストの同じ方向の点で、同位角ができてイコールだと分かる。例えばDとHが繋がった際も、同じように処理することができる。錯角も似たような感じで処理できる。


sum_angle_lstで角が二種類できる問題は、小さい方は角が180°以下だと分かった時に登録して、大きい方は180°以上だと分かった時に「360 - 角」で登録すれば良いのではないか。別に二種類作っても仕方ないし。
180°以下だと分かる時っていうのは、例えばその合計の角が三角形に含まれる時などだろう。あとは、平行四辺形に含まれる時だとか。
180°以上だと分かる時っていうのは、例えばその合計の角が直線を含む時などではないか。処理する流れが違うならば、sum_angle_lstとは別にリストを作っても良いかもしれない。

いや二種類作った方が有利になることもあるかな?どちらか分からない。がもちろん、解消不可能な問題というわけでは無いだろう。180°以下だと分かる前に登録して、そんなに意味があるのかどうか。


じゃあそういうのはどうするかは後から決めていくとして、作図の問題に戻る。

まず、今考えた方法で、ACを作図してみよう。

まず最初の設定を作成する。

graph = {
        "A" : [
            [["B"], []],
            [["D"], []]
        ]
        ,
        "B" : [
            [["A"], []],
            [["C"], []]
        ]
        ,
        "C" : [
            [["B"], []],
            [["D"], []]
        ]
        ,
        "D" : [
            [["A"], []],
            [["C"], []]
        ]
    }

    angle_equ = {
        "ABC" : 0,
        168 : 0,
        "BCD" : 1,
        108 : 1
    }

    side_equ = {
        "AB" : 0,
        "BC" : 0,
        "CD" : 0
    }

各点において、繋がっているものが更に別の繋がっているものと繋がっているということは無く、三角形は見つからない。
angle_equも、graphを見て対頂角は見つからないし、並行も無い。
sum_angle_lstも、3つ以上の辺?を持つ点は無し。sum_side_lstも、どの点を見ても通り過ぎているような辺は無い。
それで何も生まれない、最初の状態とイコールになる。


ACを作図する。

graph = {
        "A" : [
            [["B"], []],
            [["D"], []],
            [["C"], []]
        ]
        ,
        "B" : [
            [["A"], []],
            [["C"], []]
        ]
        ,
        "C" : [
            [["B"], []],
            [["D"], []],
            [["A"], []]
        ]
        ,
        "D" : [
            [["A"], []],
            [["C"], []]
        ]
    }

    angle_equ = {
        "ABC" : 0,
        168 : 0,
        "BCD" : 1,
        108 : 1
    }

    side_equ = {
        "AB" : 0,
        "BC" : 0,
        "CD" : 0
    }

各点を見ていくと、まずAと繋がっているBが、別にAと繋がっているCとも繋がっている。つまり三角形ABCがある。更にAからDを見ると、これもCと繋がっている。つまり三角形ACDがある。

triangle_lst = {
        "ABC" : ["BAC", "AB", "ABC", "BC", "ACB", "AC"],
        "ACD" : ["CAD", "AC", "ACD", "CD", "ADC", "AD"]
    }

次にangle_equ。対頂角は見つからない。

sum_angle_lst。3つ以上の辺を持つ点が2つある。
点Aの場合、角の種類としてはBAD、BAC、CADの3つがあるはず。単純に文字だけで考えると、「"BAD" + "BAC" = "CAD"」、「"BAD" + "CAD" = "BAC"」、「"BAC" + "CAD" = "BAD"」というのがあり得るはず。
しかし実際にあるのは3番目の「"BAC" + "CAD" = "BAD"」だけ。1番目は、BADの逆と普通のBACだと逆のCADになるらしい。2番目も、逆のBADと普通のCADで逆のBAC。

三角形ABCとACDが手がかりにならないかな。
例えばこれで、四角形ABCDの内角が360°であることが分かって、みたいな。

他に、小さな角と小さな角で180°以上の角になる場合も含めて考えて、少なくともこの条件を満たしたら180°以下の角の和として登録して良いのではないか。
角1と角2が1つの辺で区切られていて、しかも和の部分が180°以下。

graphのAを見ると、2つの三角形の角が2つAに含まれていて、それはACという辺で共通していて…。いや、ACで共通していても同じ側だったら駄目だからな。
2つの三角形で四角形ABCDが分かって、それをACで区切ったわけだから、角の和が成立する、という考え方はどうか。
しかし、それも、考えてみれば、1つの角だけが極端に大きい場合が考えられてしまう、細い三角形の底辺同士を貼り付けたような。いや、角Bと角Cで残りは180°無いから、それはあり得ないのか。ということは、四角形が見つかって、残りが180°無いという理由で、角の和が登録できてしまうのか。
もう一方の点Cでも同じだろう。いやこれは、四角形である必要も無く、とにかく2つの三角形の辺が共有されていて、その三角形の角の和が180°以下だったら良いのか。

sum_angle_lst = [
        ["BAC", "CAD", "BAD"],
        ["ACB", "ACD", "BCD"]
    ]

sum_side_lstはgraphを見る限り無し。

これで1辺作図のセットアップは十分に終わっている。


次は更にその上に、辺BDも作図してしまう。

graph = {
        "A" : [
            [["B"], []],
            [["D"], []],
            [["C"], []]
        ]
        ,
        "B" : [
            [["A"], []],
            [["C"], []],
            [["D"], []]
        ]
        ,
        "C" : [
            [["B"], []],
            [["D"], []],
            [["A"], []]
        ]
        ,
        "D" : [
            [["A"], []],
            [["C"], []],
            [["B"], []]
        ]
    }

    angle_equ = {
        "ABC" : 0,
        168 : 0,
        "BCD" : 1,
        108 : 1
    }

    side_equ = {
        "AB" : 0,
        "BC" : 0,
        "CD" : 0
    }

    triangle_lst = {
        "ABC" : ["BAC", "AB", "ABC", "BC", "ACB", "AC"],
        "ACD" : ["CAD", "AC", "ACD", "CD", "ADC", "AD"]
    }

    sum_angle_lst = [
        ["BAC", "CAD", "BAD"],
        ["ACB", "ACD", "BCD"]
    ]

さっき言った手順で、三角形ABDとBCDは見つかる。

次にangle_equ。対頂角はあるはずなんだが、まだ見つからない。

sum_angle_lst。2つの三角形を持ち、BDが共通していて、角が168°なんで、B側は登録される。もう一方もさっき書いたような感じできっと登録される。

で、四角形ABCDを対角線で突っ切っているわけだから、中心に交点があるのが分かるはず。
その直後のイメージを用意してみた。まだ三角形とかが用意されていないというか、実際にどういう順番になるかは分からないけど。

graph = {
        "A" : [
            [["B"], []],
            [["D"], []],
            [["E", "C"], []]
        ]
        ,
        "B" : [
            [["A"], []],
            [["C"], []],
            [["E", "D"], []]
        ]
        ,
        "C" : [
            [["B"], []],
            [["D"], []],
            [["E", "A"], []]
        ]
        ,
        "D" : [
            [["A"], []],
            [["C"], []],
            [["E", "B"], []]
        ]
        ,
        "E" : [
            [["A"], ["C"]],
            [["B"], ["D"]]
        ]
    }

    angle_equ = {
        "ABC" : 0,
        168 : 0,
        "BCD" : 1,
        108 : 1
    }

    side_equ = {
        "AB" : 0,
        "BC" : 0,
        "CD" : 0
    }

    triangle_lst = {
        "ABC" : ["BAC", "AB", "ABC", "BC", "ACB", "AC"],
        "ACD" : ["CAD", "AC", "ACD", "CD", "ADC", "AD"],
        "ABD" : ["BAD", "AB", "ABD", "BD", "ADB", "AD"],
        "BCD" : ["CBD", "BC", "BCD", "CD", "BDC", "BD"]
    }

    sum_angle_lst = [
        ["BAC", "CAD", "BAD"],
        ["ACB", "ACD", "BCD"],
        ["ABD", "CBD", "ABC"],
        ["BDC", "ADB", "ADC"]
    ]

まあ今日はここまでで良いか。なんかつまりこういうイメージだ。