ジュニア算数オリンピック 二次元上のユークリッド幾何の問題 その16
【随時更新】ユークリッド幾何学の定理や作図まとめ - ニート歴10年からの数学日記 を機械的に適用して、解答に至れるかを探る。今はこの自分で書いたプログラムを使っている。考察はユークリッド幾何学の原理についてのメモ - ニート歴10年からの数学日記とジュニア算数オリンピック04年度ファイナル問題6 辺の和について、三角形の検出について - ニート歴10年からの数学日記。
06年度トライアル問題 問題9
『図の四角形ABCDはAB=BC=CDで、角B=168度、角C=108度です。角Dの大きさを求めなさい。
』
前回の続き。
作図
以下5種類の作図をしていく。直接作図したもの以外に三角形や、あるいは正四角形や正五角形ができていたら、次の定理ループで角度が明らかになる可能性がある。
- 点と点を結んで線にする
- 点と点の距離の分だけ線を延長
- 2点と、その間の垂直線とどこか1辺の交点による、二等辺三角形の作図
- ある1辺と同じ長さの辺を別の辺に落とすことによる二等辺三角形の作図
- 同じ図形の作図(同じ長さの辺の所に)
- 正四角形
- 正五角形
じゃあ、1ステップ目の同じ図形の作図から。
それぞれの辺ごとに、そのまま点の位置を逆転させるのと、辺を軸に返すのと、辺を軸に返した上で点の位置を逆転させるのとで、3種類ある。
いや、同じ長さの辺とかがあるから、その同じ長さの辺による組み合わせもあるのか。
複製して、辺ABの位置をどこかに移す場合から考える。
まず対象はAB、BC、CDだが、外側に作っても新しく三角形が作られないので、本当は外側への2種類の作図は考えても意味は無い。
ABを軸にそのまま返したような作図の場合で考えると、点CとDに対応して、点EとFを追加する。そして辺をgraphに登録し、対応するangle_equとside_equを登録する。
辺BEは、角ABCのネガティブ側、角ABC_nを割っている。角ABEも168°で、角CBEも360°以下なので、ABE + CBE = ABC_nと登録できる。
辺AFは、角BADのネガティブ側、角BAD_nを割っている。角BAFはポジティブ(つまり180°以下)なわけだが、もう一つの角は、いや、その2つの角がそれぞれ84°以下なので、ネガティブだと断定できるわけか。BAF + DAF_n = BAD_n。
しかし、また比較が出てきた。どうも作図において、比較を登録しておく機能は必要みたいだ。
また、今回は判明したが、判明しない場合もあり得る。そうすると、例えば角ABCと角ABC_nという表記では無く、発見された順にABC_1とABC_2と表記するべきなのかもしれない。ABC_1 + ABC_2 = 360で、ポジティブだと分かったら例えばABC_2 < 180。まあ試してみるか。
今回は始まったばかりなんで、次の作図から試してみることにしよう。
でとにかく、複製してABの辺を移すのの対象は、ABとBCとCDの内側ということになる。
ABのAとBを反転させて移す場合、同じようにCとDだったのをEとFと名付けるとして、さっき言ったように複製することになる。角A < 角Bなので、元々の角ABCは割られることになり、ABF_1 + CBF_1 = ABC_1、割られる角がABC_1 < 180なので、ABF_1 < 180、CBF_1 < 180だ。
また元々の角BADはむしろ割る側になる。BAD_1 + DAE_1 = BAE_1、これも同じく割られる角がBAE_1 < 180なので、BAD_1 < 180、BAE_1 < 180。
うーん、ちょっと分かりにくい気もするな。でも当初はBAD_1やBAD_2とかいう風に名付けて、分かり次第BAD_pやBAD_nと名付けるか?どうしようかな。
交点が分からない状態は、3D空間での作図を想像して貰えれば概念的には近いと思う。必ず交点を見つける必要があるというわけでは無い。
で、この時に、新しく複製した元ADと元CDで、どちらに交点が発生するかは、俺の記憶が正しければ分からないという結論だったような。実際にはADと元ADが交わってそれで終わりなんだろうが。
ADと元ADは、辺と辺が交わるかという問題なんだろうな。CDと元ADも、BCを介して同じ問いに持ち込むことができるか。ADと元CDも、だとしたらきっと似たような感じ。CDと元CDはどうなんだろうな。ABCを固めてACが明らかになればって感じなのか?
しかし、その辺と辺が交わるか、っていうのが分からないのだよな。休憩(別に何度でも休憩はしているわけだが)。
今までの作図の道具まとめ
ちょっといきなり脱線するようだけど、今までの作図における道具をまとめてみた。そういうことをしないと考えがまとまらない。
5種類ある作図のうち、点と点を結んで線にするのと、点と点の距離の分だけ線を延長は、特に無し。特に後者はまだ出てきてないだけかもしれない。
同じ長さの辺を繋がっている辺に落とすことによる二等辺三角形の作図
条件は2つある
1・繋がっている辺との角が90°以下
説明1:それ以上だと垂線より長くなって届かない
説明2:同じ長さの辺を落とす時に、元々の境目が90°以上で、二等辺三角形で180°以上になるので無理
説明3:同じ長さの辺を落とす時に、一番端が短いものは、どんどん元の辺によっていって、元の辺の位置で一致するので無理
2・底辺の中心と頂点の位置関係
- 底辺の中心と頂点を結んだ時の頂点角の角度と、頂点から垂線を垂らした時の頂点角の角度(180 - 90 - 元の2辺の角度) 後者が大きければ無理
- あるいは、底辺の半分と、垂線を垂らした時の辺の長さ 後者が大きければ無理
※ちなみに他にも「底辺の半分と頂点を結んだ長さと、垂線の長さを比較する」という間違った説明があった
同じ図形の同じ長さの辺への作図
- クラスタの底辺を重ね合わせた時に、底辺の角度が互い違いになっているなら、どこかで交点が発生する。2辺ならどちらの辺が交わるかも明らかになる(なぜなら二等辺三角形だと角度が半々になって、そこからは辺が長い方が角度は浅くなるから)(3辺以上になると、分からないのではないか)
- 図形を重ね合わせた時に、一つ一つの辺の関係を問うていく。1つの辺を挟んで存在する2つの辺と辺は交わるか。
実装課題
- クラスタの登録
クラスタを対角線で突っ切っている場合、真ん中に交点ができる
- 角の具体的な足し算引き算も実装しなければならないのではないか、内角など
角1 + 角2 + 角3 = 180。
x + 2*x + 2*x = 180。
A + B = 72.5、B + C = 78、A + B + C = 121。B = 29.5。
- 比較も実装したい。具体的な数値が分からない状態での上下の判断に特に注目
内角から判断して、何度以下かは分かったりする
どちらが長いかの判断で、元々2つの辺が等しく、その間の角が60°以上の場合、下の辺はそれらより長い、60°以下の場合、下の辺はそれらより短い
- 角の名前の変更 ABC_1・ABC_2から、どちらかが180°以下と判明し次第、ABC_p・ABC_n。
- 面積比と底辺比 でもこれはどうなんだろう。
作図の問題に戻る
で、その1辺を挟んだ2辺が交わるかだけど、これは三角関数?が無いと分からないんじゃないかなあ、多分。
まあだからつまり、元ABを、BCやCDに、そのままと反転と2通りずつ作図していくのも、これは分からないという結論になる。つまり作図はしない。
いや、後から振り返ると間違いで、角Bを軸にABとBCを入れ替えるような作図は、2辺なのでどちらに交わるか分かる。
そのようにABとBCを入れ替える場合、BCとCDを入れ替える場合の2種類を、実際に試してみる。
まずABとBCを入れ替えるような作図。
まず一番最初のスタート地点を用意する。
graph = { "A" : [ [["B"], []], [["D"], []] ] , "B" : [ [["A"], []], [["C"], []] ] , "C" : [ [["B"], []], [["D"], []] ] , "D" : [ [["A"], []], [["C"], []] ] } triangle_lst = { } cluster_lst = [ ["BAD_p", "ABC_p", "BCD_p", "ADC_p"] #こういうものは自動化したいが、これは自明では無く問題文の情報なので記述する ] angle_equ = [ ["ABC_p", 168], #しかしこのpというのはどうなんだろうな。普通の無しの方が分かりやすくないかな、試してはみるけど ["BCD_p", 108] ] side_equ = [ ["AB", "BC", "CD"] ] angle_less_than = [ ] side_less_than = [ ] sum_angle_lst = [ #2つ以上の足し算も記述することにする。答えも2つ以上にするかは、迷うけど、そのつもりで行く ] sum_side_lst = [ ]
なんか随分、必要なリストが増えてしまった。今は試行錯誤の段階で、必要無くなったら減らすけど、おそらく必要ではないかと思う。
で、考えたけど、クラスタからsum_angle_lstを読み取る。あと、pがある分のnを登録する。
あと、angle_less_thanも更新できそうだ。これからは上から確認していくことにしよう。
sum_angle_lst = [ #左辺の総和 = 右辺の総和 [["BAD_p", "ABC_p", "BCD_p", "ADC_p"], [360]], [["BAD_p", "BAD_n"], [360]], [["ABC_p", "ABC_n"], [360]], [["BCD_p", "BCD_n"], [360]], [["ADC_p", "ADC_n"], [360]] ] angle_less_than = [ #左辺の総和 < 右辺の総和 [["BAD_p"], [84]], [["ADC_p"], [84]] ]
本当の流れはどうなるかは分からないけど、とりあえず上から確認していったし、三角形も無いので、次の作図に進むことにする。
ABとBCを入れ替えたような図を作図し、元DをEと名付ける。いや違うな、ABをCBと対応するように作図し、被ったものは消すか。ということは、元Cに対応するのがEで、元Dに対応するのがFか。
いや書いてみたけど、まだプログラムみたいに厳密に記述するのは早いな。流れすら確立して無いのだから。
まず元Aと元Dの辺、つまりCFが、点Cに属する角を、それぞれ割っているかを確認する必要がある。
角BCD_pと角BCF_pを比較して、BCD_pの方が大きいので、BCD_pを割ったと判断する。
…もう駄目だと思って昼寝していたけど、これって元の体系に合流できないかな。なんか逃げっぽいけど。いつか合流させたいと思っていたけど、今のタイミングで合流して良いんじゃないかな。
まあ明日一回だけ、それを試してみようかな。ABとBCを入れ替える場合を。いや、逃げかなこれは。
ジュニア算数オリンピック 二次元上のユークリッド幾何の問題 その15
【随時更新】ユークリッド幾何学の定理や作図まとめ - ニート歴10年からの数学日記 を機械的に適用して、解答に至れるかを探る。今はこの自分で書いたプログラムを使っている。考察はユークリッド幾何学の原理についてのメモ - ニート歴10年からの数学日記とジュニア算数オリンピック04年度ファイナル問題6 辺の和について、三角形の検出について - ニート歴10年からの数学日記。
06年度トライアル問題 問題9
『図の四角形ABCDはAB=BC=CDで、角B=168度、角C=108度です。角Dの大きさを求めなさい。
』
前回の続き。別件(旅行の計画)であまり寝てないんで、説明が分かりにくいかもしれない。
一晩考えてみたのだが、この問題は3Dで思い描くと議論が簡単というか本質的になるかもしれない。
3Dでも三角形定理ループは回せる。ただ、四角形つまり4つの点のクラスタとなると、実は内角は360°とは限らないと分かる。確かに限界は360°だが、例えるなら折りたたみ傘を畳むような感じで、ほとんど0°まで減らすことができる。
またangle_equだが、対頂角は3Dでも成立するし、平行的な関係もあると分かる。その並行的な関係同士では、お互いに辺が跨った時に、そのまま突っ切っていった辺と、その並行の予め登録しておいた同じ方向に、同位角ができる。ただ、まだ平行だと分かっていない辺と辺で同位角ができたからといって、それが平行とは限らない。というのも、ある辺の交わりがあったとして、3Dで1辺に干渉せずに同じ大きさの角を作ることは可能だからだ、そしてそれは平行では無い。平行にするには、合同の三角形の1辺同士を反転させて合わせ、それだけでなくその離れた点同士も結んで、それが同じように合同な三角形の1辺同士を反転させて合わせたようなものになっている必要があるのではないか。
side_equは今まで通り。sum_side_lstも今まで通りできると分かる。
一番の問題は、やっぱりというか、sum_angle_lstだ。今までは、1つの点から3つの辺が伸びているような時に、1つの辺が2つの辺からなる角を割っているものだと思っていた。しかし実際には、3Dで考えてみると1つの点から伸びている辺は、傘の骨のような感じでバラバラな方向に伸びているかもしれないわけだ。2Dのユークリッド幾何学は、そこに制約を加えたものだと考えるべきなんじゃないか。
3次元の空間において、2次元のユークリッド幾何学をやるにはどうすれば良いか、という考え方をすると分かりやすいのかもしれない。あのいちいち角の和を登録していく作業は、振り返ってみるとかなり本質的なものだったと分かる。
例えばこの問題において、点AとCを繋げる時は、ただ点AとCを繋げるだけでなく、角BADを割るという作業だと考える必要がある。これは全然自明なことでは無い。
まだどうするかは手探りだが、180°以下の角BADは今まで通り角BADと呼んで、「360 - BAD」の方は「BAD_n」と呼ぶことにしてみる。このnはネガとかnotとかのnだ。もし駄目だったらまた元に戻せば良い。
四角形ABCDは、だから点が繋がっているだけでは無く、普通の角4つが向き合っているクラスタだと考えれば良いのではないか。
この方針で最初から、(おそらく部分的に自然言語で)作図をしてみる。
作図
以下5種類の作図をしていく。直接作図したもの以外に三角形や、あるいは正四角形や正五角形ができていたら、次の定理ループで角度が明らかになる可能性がある。
- 点と点を結んで線にする
- 点と点の距離の分だけ線を延長
- 2点と、その間の垂直線とどこか1辺の交点による、二等辺三角形の作図
- ある1辺と同じ長さの辺を別の辺に落とすことによる二等辺三角形の作図
- 同じ図形の作図(同じ長さの辺の所に)
- 正四角形
- 正五角形
まず問題文や図から情報を読み取る。
四角形ABCDがある。四角形ABCDは、角BAD、角ABC、角BCD、角ADC、のクラスタだ。
角ABCは168°、つまり角ABC_nは192°。角BCDは108°、角BCD_nは252°。
辺ABとBCとCDはイコール。
対頂角も平行線も無いし、他の角の和とか辺の和とかも無し。
では1ステップの作図に入る。
点AとCを繋げる。四角形ABCDがクラスタとして登録されているので、この線によって角BADと角BCDが割られる。
BAC + CAD = BAD。
ACB + ACD = BCD。
元々ポジティブ(ネガティブのnに対して)な角を割っているので、BACやCADなどもポジティブだと分かる。
点BとDを繋げるのも似たような感じだろう。
で、次は線の延長。
まず辺ABを点A側に延長してみる。また、この延長はさっき言ったように角の分割でもあるべきだ。
延長側に新しく追加した点をEとして、角BAEは180°、180°の場合は、三次元で想像して貰えれば分かると思うけど、BAE_nを想定する必要は無い。辺ADと辺AEでできる角は、180°に一つでも他の角が入っているので、ポジティブだと分かる。
つまり、角DAE + 角BAE = 角BAD_n、だと分かる。それで登録しておく。(この角の足し算は、数値の足し算というより、隣接の表現であるべきなのかもしれない。まだ分からん)
1ステップ目においては、どの点も似たような感じだろうと思う。
次は「2点と、その間の垂直線とどこか1辺の交点による、二等辺三角形の作図」。
この、交点がどこにできるかを探るという作業は、おそらくユークリッド幾何学でもある工程で、だからおそらくそこまで技術的な問題は無いのではないかと思う。
まず辺ABを底辺とした二等辺三角形を考える。
すると、もしこの角BADが大きく、角ADCが小さい場合、辺ABの垂直二等分線はCDと交わることもあり得る。もちろん実際には、点AからBCDと形は決まっているので、それを結んだ辺ADによってできる角度も決まっている。しかし三角関数?が無い以上、おそらく判断はできないのではないか。辺CDについても同じように言えるだろう。
辺ADについては、実はこれは判断ができてしまう。
三角形ABDを想定し、ABよりBDが長ければ、三角形ABDにおいてはBDに交わる。そして三角形BCDに着目すると、その角Cが60°以上なので、正三角形よりも底辺が大きいと分かる。よってBDとABだと、BDの方が長いと分かる。
三角形ACDを想定しても、同じことが言える。
ということは、クラスタABCDにおいて、ABより右で、CDより左に交わるので、BCに交わると分かってしまう。
しかしこれは理論上の話で、実際にはそういう作図はしないことに暫定的に決めていたんだった。
辺BCについても同じようなことが言える。
次は「ある1辺と同じ長さの辺を別の辺に落とすことによる二等辺三角形の作図」。
どうすれば良いか分からない。振り返ってみると、分からないなら作図しなければ良いんじゃないかで終わっているけど。
始めたばかりだけど、昼寝でもしてまた取り組むことにする。
これは、本質的には、円と線がどこで点を作るかという問題なんじゃないか。
円と円が点を作るかは、今考えれば簡単で、円の距離が分かれば作るし、分からなければ分からない。
考えてみると、条件は2つある。
1つ目は、円の中心から垂線を垂らして、それが円の長さより大きいか小さいか。というよりはつまり、例えばこの場合にABをADに下ろそうとしているなら、BADの角度が90°より大きいか小さいかというだけだろうな。まあ自分でも変な説明になったと思うけど、90°よりも小さければ、当たり前だけど遠すぎて無理ということは無い。
1つ目が円が辺に届かない場合だとしたら、2つ目は、円の内側に辺が入り込んでしまうような場合。まあでもこれは、つまり1角が既に決まっていて、二等辺三角形だからもう1角も決まっていて、ということは3角が決まっているということで、これは三角関数?の問題ということになってしまうのではないか。できあがるはずの三角形の底辺より長いか短いかで。
いやこの場合は、ADの中心と点Bの位置関係の問題なのではないか。点Bの方が左にあるなら、作ることができる。しかしどう判定すれば良いんだろう。休憩。
さっき、円と円で交点を作るかで、円の距離が分かれば作ると書いたが、あれは間違いだった気がする。
もし、何の間接的な接点も無い円と円があったとして、その二つはその後も絶対に接点を持ち得ないと考えるべきだ。
また、もし辺の連なりがあって、その端同士で円と円があったとして、その辺の連なりは3D空間でヒョロヒョロしているだけで、その二つの関係は、おそらく間を三角形だとかで固めないと全く分からない。これはあくまで例えだが、その連なりの2辺で三角形を作ると、辺が1本減る。それを繰り返せば、いずれ端と端の関係も明らかになるだろう。それが円と円であれ、辺と辺であれ、円と辺であれ。
話を戻すが、ADの中心と点Bの位置関係は、一つは、点BからADに垂線を垂らした時の角Bの角度(180 - 90 - 角A)と、ADの中心と点Bを結んだ時の角Bの角度(どうなるかは分からない、明らかになれば)を比較すれば分かるだろう。
もう一つは、点BからADに垂線を垂らした時の辺の長さと、ADの中心と点Bを結んだ時の辺の長さを比較すれば分かるだろう。
いや、下の辺を比べてもそれでも良いのかな?
なんか曖昧な感じだけど、くり返している内に固まってくるだろう、多分。
次の作図が大変だろうから、今日はここで切ることにする。
ジュニア算数オリンピック 二次元上のユークリッド幾何の問題 その14
【随時更新】ユークリッド幾何学の定理や作図まとめ - ニート歴10年からの数学日記 を機械的に適用して、解答に至れるかを探る。今はこの自分で書いたプログラムを使っている。考察はユークリッド幾何学の原理についてのメモ - ニート歴10年からの数学日記とジュニア算数オリンピック04年度ファイナル問題6 辺の和について、三角形の検出について - ニート歴10年からの数学日記。
06年度トライアル問題 問題9
『図の四角形ABCDはAB=BC=CDで、角B=168度、角C=108度です。角Dの大きさを求めなさい。
』
前回の続き。2ステップ目は長いんだが、気が済むまでやり続ける。
作図
以下5種類の作図をしていく。直接作図したもの以外に三角形や、あるいは正四角形や正五角形ができていたら、次の定理ループで角度が明らかになる可能性がある。
- 点と点を結んで線にする
- 点と点の距離の分だけ線を延長
- 2点と、その間の垂直線とどこか1辺の交点による、二等辺三角形の作図
- ある1辺と同じ長さの辺を別の辺に落とすことによる二等辺三角形の作図
- 同じ図形の作図(同じ長さの辺の所に)
- 正四角形
- 正五角形
で前回は2ステップ目の、点と点を結んで線にする同士を試したんだった。今回は、点と点を結んで線にすると、それ以降の組み合わせを試していく。
前回の、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 } 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"] ]
で、どの線の延長も、2ステップ目では三角形を生まないので、これは本当はスルーしたい。
1回ABをA側に延長してみる。するとこうなる。
graph = { "A" : [ [["B"], ["E"]], [["D"], []], [["C"], []] ] , "B" : [ [["A", "E"], []], [["C"], []] ] , "C" : [ [["B"], []], [["D"], []], [["A"], []] ] , "D" : [ [["A"], []], [["C"], []] ] , "E" : [ [["A", "B"], []] ] } angle_equ = { "ABC" : 0, 168 : 0, "BCD" : 1, 108 : 1 } side_equ = { "AB" : 0, "BC" : 0, "CD" : 0, "AE" : 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"] ]
それで、延長した辺上にある点、AとEを探して、三角形が発生していないか見ていく。当然新しく発生していないと分かる。それで、ようやくこのステップはキャンセルできる。
この流れによるキャンセルをこのACの作図と何らかの辺の延長の組み合わせの全てで行う。
次は、ACの作図と「2点と、その間の垂直線とどこか1辺の交点による、二等辺三角形の作図」の組み合わせ。
今回はどの辺も三角形に属しているのでやりやすい(いやABだけ考えてもそうでは無かった)。交点の判断はこの試行錯誤の核の一つだと思うが。
まず、最初の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 } 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"] ]
ABの垂直二等分線と交点を持つ辺を考えると、本当はACとADが引っかかるべきだ。
ACは三角形ABCに着目すれば良い。
ADは、本当は交わるのが決まっている。なぜならAとBとCとDの位置関係は、相似形ながら決まっているから。でもそういうのはおそらく、三角関数と俺が仮に呼んでいるものを使う必要がある。
もし、CDが長かったら、ADと交わらない場合もあり得る。と考えると、ADを伸ばしても四角形なわけだし、現在判明している角だけでの判断は難しいのではないか。BとDを繋いで判断する必要がある、がそれを今すべきかどうかのどちらか。まあ仮にしない方を選んでみる。
ABを底辺としたAC上への二等辺三角形の作図は、こうなる。
graph = { "A" : [ [["B"], []], [["D"], []], [["C", "E"], []] #ちょっと試しに、近い順じゃなくしてみる。そういう順番が分からない方が多いのではないか。それで問題が無ければそれが良い ] , "B" : [ [["A"], []], [["C"], []], [["E"], []] ] , "C" : [ [["B"], []], [["D"], []], [["A", "E"], []] ] , "D" : [ [["A"], []], [["C"], []] ] , "E" : [ [["A"], ["C"]] ] } angle_equ = { "ABC" : 0, 168 : 0, "BCD" : 1, 108 : 1, "BAE" : 2, "ABE" : 2 } side_equ = { "AB" : 0, "BC" : 0, "CD" : 0, "AE" : 1, "BE" : 1 } 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"] ]
これで三角形を探すなり何なりする。
試行錯誤したいのは、交点の判断と、平行線関係と、sum_angle_lst関係。3番目がまだ残っているので、続けることにする。
まず三角形を探す。
ABEを発見。BCEを発見。まあ考えてみれば、追加した辺BEについて探せば良かったのか。
triangle_lst = { "ABC" : ["BAC", "AB", "ABC", "BC", "ACB", "AC"], "ACD" : ["CAD", "AC", "ACD", "CD", "ADC", "AD"], "ABE" : ["BAE", "AB", "ABE", "BE", "AEB", "AE"], #今回は角を今までどおり記述するが、"A_[0][0]_[2][0]"という記述もアリだ。どう記述しても順番的に角BAEを表しているということは分かるわけだし。あるいはそれぞれの辺の[0]が変更されないようなら"BAC"でも良いかもしれない "BCE" : ["CBE", "BC", "BCE", "CE", "BEC", "BE"] }
次に対頂角と並行が発生しないことを確認する。
sum_angle_lstを追加した辺BE上の点、つまり点Bと点Eに着目して更新する。
点Bも点Eも辺を共有した三角形を2つ含み、四角形のクラスタをABCEと、その共有した辺BEを挟む形で形成するので、どちらの角の和も登録できると分かる(例えば四角形がABECだと、これは同じ方向に展開する角だと分かり、角の和としては登録してはいけない)。
sum_angle_lst = [ ["BAC", "CAD", "BAD"], ["ACB", "ACD", "BCD"], ["ABE", "CBE", "ABC"], ["AEB", "BEC", 180] ]
graphに着目してsum_side_lstを更新する。点Eだけ見れば良い。
sum_side_lst = [ ["AE", "CE", "AC"] ]
あとは三角形定理ループにかける感じかな。graphの内容自体は書き換わらない。次。
ACの二等分線は、まず三角形ABCだと点Bに交わるだろう、角度が同じなので。平行線は無いし、sum_angle_lstも同じ。
三角形ACDだと、その角Cが102°なので、残りがせいぜい78°という理由で、辺ADと交わる。まあこれも後はいろいろと同じだろう。
ADの二等分線は、三角形ACDだと、もしACがCDより長ければ、ACに交わると言えるのではないか。そして三角形ABCにおいて、もしそれぞれの辺の長さが同じだとしたら、角Bは60°で、それより大きいので、CDよりACが長いと言えるのではないか。
それをどうやって実装するかだがな。side_equ[0] < AC、なんていうのは。それが無理なら、比較はできないんで、どちらに交わるか分からずに、交点は考えないということになるだろう。とかで。
辺ABに交わるかも、三角形ABDで、同じように判断をすることが原理的には可能だろうが、とりあえず暫定的に判断しないことにしたんだっけか。
辺BCに交わるかが一番難しい。まあ、辺ABに交わらず、辺CDにも交わらないとなると、消去法でBCに交わることになるはずではあるんだがな。
このステップにおいては、どの辺と辺も、そういう確認方法が可能ではあるか。使うかはともかく。
それらにおける角の和でも、三角形を作図して、四角形にして共有する辺を挟むかを確認することができるかな?
BCの二等分線の作図。ABCではACに交わる。CDには108°なので交わらないので、ABとCDに交わらないという理由でADにも交わる。まあACへの作図を試しにやってみようか。
graph = { "A" : [ [["B"], []], [["D"], []], [["C", "E"], []] ] , "B" : [ [["A"], []], [["C"], []], [["E"], []] ] , "C" : [ [["B"], []], [["D"], []], [["A", "E"], []] ] , "D" : [ [["A"], []], [["C"], []] ] , "E" : [ [["A"], ["C"]], [["B"], []] ] } angle_equ = { "ABC" : 0, 168 : 0, "BCD" : 1, 108 : 1, "CBE" : 2, "BCE" : 2 } side_equ = { "AB" : 0, "BC" : 0, "CD" : 0, "BE" : 1, "CE" : 1 } 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"] ]
で、いやもう特に言うこと無いな。手なり。
ADに交わるかは、辺BDを作図する必要があって、でそういうことはしないと暫定的に決めたわけだし。
角の足し算とか引き算とかについても実装しなければいけないと今気付いた。三角形ABCで168°と他同じのが2角とかで。
CDの垂直二等分線。三角形ACDに着目すると、角Cは102°なので、辺ADに交わる。
graph = { "A" : [ [["B"], []], [["D", "E"], []], [["C"], []] ] , "B" : [ [["A"], []], [["C"], []] ] , "C" : [ [["B"], []], [["D"], []], [["A"], []], [["E"], []] ] , "D" : [ [["A", "E"], []], [["C"], []] ] , "E" : [ [["A"], ["D"]] ] } angle_equ = { "ABC" : 0, 168 : 0, "BCD" : 1, 108 : 1, "DCE" : 2, "CDE" : 2 } side_equ = { "AB" : 0, "BC" : 0, "CD" : 0, "CE" : 1, "DE" : 1 } 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"] ]
まあ後は手なりじゃないか。それから三角形定理ループ。
次は、ACの作図と、「ある1辺と同じ長さの辺を別の辺に落とすことによる二等辺三角形の作図」の組み合わせ。
まず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 } 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"] ]
ABと同じ長さの辺をAD上に落とすというのがあり得る。また逆にAからBCに作図するという場合があり得るはずだが、その場合は168°が2つになるので無理。
次のBCは、BからCDに落とすというのがあり得るが、これも108°が2つになるので無理。
CDのDからの、BCに落とすというのも同じ理由で無理で、ACに落とすのも102°が2つになるので無理。CからADは可能だろう。
ADの場合の、AからCDと、DからABは可能なんだろうか。
まずABと同じ長さの辺をAD上に。
graph = { "A" : [ [["B"], []], [["D", "E"], []], [["C"], []] ] , "B" : [ [["A"], []], [["C"], []], [["E"], []] ] , "C" : [ [["B"], []], [["D"], []], [["A"], []] ] , "D" : [ [["A", "E"], []], [["C"], []] ] , "E" : [ [["A"], ["D"]], [["B"], []] ] } angle_equ = { "ABC" : 0, 168 : 0, "BCD" : 1, 108 : 1, "BAE" : 2, "BEA" : 2 } side_equ = { "AB" : 0, "BC" : 0, "CD" : 0, "BE" : 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"] ]
まあ、うん。並行は無いし、角の和も、まあ。
とか言ってたらやることが無いからな。並行が出る作図を探すか。まあいつか出てくると思うけども。
ADをCDとかABに下ろすのはどうなんだろう。一番端のACとかBDがADより短いものは、それよりAD側に寄せてもADの長さに近づいていってADで一致するだけだから、無理なんじゃないかという気はする。
ACは下の角が102°だから、ADの方が長い、つまりACの方が短いから無理。
BDもきっとそうなんだろうけどなあ。というかそもそも、そういう長さ確認をABとかCDでもすべきだったかな。まあ分からない場合は作図せずで良いんじゃないかな。
ジュニア算数オリンピック 二次元上のユークリッド幾何の問題 その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辺の交点による、二等辺三角形の作図
- ある1辺と同じ長さの辺を別の辺に落とすことによる二等辺三角形の作図
- 同じ図形の作図(同じ長さの辺の所に)
- 正四角形
- 正五角形
今回は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"] ]
まあ今日はここまでで良いか。なんかつまりこういうイメージだ。
ジュニア算数オリンピック 二次元上のユークリッド幾何の問題 その12
【随時更新】ユークリッド幾何学の定理や作図まとめ - ニート歴10年からの数学日記 を機械的に適用して、解答に至れるかを探る。今はこの自分で書いたプログラムを使っている。考察はユークリッド幾何学の原理についてのメモ - ニート歴10年からの数学日記とジュニア算数オリンピック04年度ファイナル問題6 辺の和について、三角形の検出について - ニート歴10年からの数学日記。
06年度トライアル問題 問題9
『図の四角形ABCDはAB=BC=CDで、角B=168度、角C=108度です。角Dの大きさを求めなさい。
』
セットアップ
三角形、同じ大きさの角、同じ大きさの辺のディクショナリ(辞書)と、角の和、辺の和のリストをそれぞれ作成する。
まず三角形を探す。点に着目して、繋がっている点が他の繋がっている点と繋がっていたら、それは三角形。
着目した点。繋がっている点。 三角形。
A。B、D。
B。C。
triangle_lst = {} #今見ると辞書なのに名前にリストがあるのはマズいな
次に同じ大きさの角の辞書を作成する。
問題文の条件を見る。今回は迷ったが、試しに角ABCが168°とイコールと考えてみることにする。
対頂角や平行線の同位角や錯角は今のところ無し。
同じ大きさの角。
ABC、168。
BCD、108。
angle_equ = {
168 : 0,
"ABC" : 0,
108 : 1,
"BCD" : 1
}
次に同じ大きさの辺の辞書を作成する。
問題文の条件を見る。
同じ大きさの辺。
AB、BC、CD。
side_equ = {
"AB" : 0,
"BC" : 0,
"CD" : 0
}
角の和のリストを作る。
まず普通に点に着目する。しかし、2つ以上の角を持つような点は無し(厳密には360 - 角、みたいな感じであるが。しかしそれを記述しだすとアルファベット順という角への命名のルールが崩れる。必要になるまでは記述しない)。
次に三角形に着目して、外角を調べる。しかし三角形は無し。
sum_angle_lst = [ ]
辺の和のリストを作る。しかし辺が合わさったような辺は無し。
sum_side_lst = [ ]
この条件で三角形定理ループプログラムを回してみる。
角 0 : [168, 'ABC'] 1 : [108, 'BCD'] 角の和 辺 0 : ['AB', 'BC', 'CD'] 辺の和 三角形
そりゃそうだ。しかしエラーが発生しなくて良かった。
作図
以下4種類の作図をしていく。直接作図したもの以外に三角形や、あるいは正四角形や正五角形ができていたら、次の定理ループで角度が明らかになる可能性がある。
- 点と点を結んで線にする
- 点と点の距離の分だけ線を延長
- 2点と、その間の垂直線とどこか1辺の交点による、二等辺三角形の作図
- 同じ三角形を(同じ長さの辺の所に)作図
- 正四角形
- 正五角形
点と点を結んで線を作図する。
点に着目して、繋がっていない点を探す。点AとC、点BとD。
点AとCを結ぶ。
三角形を探す。辺ACに着目する。具体的には点AやCや辺ACによって発生した交点全てに着目する。
着目した点。繋がっている点。 結果。
A。B、C、D。 ABC、ACD。
C。B、D。
triangle_lst = {
"ABC" : ["BAC", "AB", "ABC", "BC", "ACB", "AC"],
"ACD" : ["CAD", "AC", "ACD", "CD", "ADC", "AD"]
}
新しく生まれた定義や対頂角や平行線の同位角や錯角を登録する。無し。
角の和を探す。点に着目する。
角の和。
BAC + CAD = BAD。
ACB + ACD = BCD。
sum_angle_lst = [
["BAC", "CAD", "BAD"],
["ACB", "ACD", "BCD"]
]
辺の和を探す。無し。
三角形定理ループプログラムを回してみる。
BAC == ACB 角 0 : [168, 'ABC'] 1 : [108, 'BCD'] 2 : ['BAC', 'ACB'] 角の和 [2] + CAD == BAD [2] + ACD == [1] 辺 0 : ['AB', 'BC', 'CD'] 辺の和 三角形 ABC : [BAC[2], AB[0], ABC[0], BC[0], ACB[2], AC] ACD : [CAD, AC, ACD, CD[0], ADC, AD]
何が新しく分かったかというと、角の[2]と、角の和の2つ。しかしこれらには全て辺ACの絶対値?というか辺AC自体が入っており、元々の何かを明らかにした作図とは言えない。よって、この1ステップではこの作図には意味が無かったと言える。
点BとDを結ぶ。
三角形を探す。辺BD上の点に着目する。
着目した点。繋がっている点。 結果。
B。A、C、D。 ABD、BCD。
D。A、C。
triangle_lst = {
"ABD" : ["BAD", "AB", "ABD", "BD", "ADB", "AD"],
"BCD" : ["CBD", "BC", "BCD", "CD", "BDC", "BD"]
}
新しく生まれた定義や、対頂角や平行線の同位角や錯角を登録する。無い。
角の和を探す。辺BDによって生まれた角に関する所だけ追加すれば良い。辺BD上の点に着目すれば良いのではないか。
着目した点。 結果。
B。 ABD + CBD = 168。
D。 ADB + BDC = ADC。
sum_angle_lst = [
["ABD", "CBD", 168],
["ADB", "BDC", "ADC"]
]
辺の和を探す。無し。
三角形定理ループプログラムを回してみる。
CBD == BDC 角 0 : [168, 'ABC'] 1 : [108, 'BCD'] 2 : ['CBD', 'BDC'] 角の和 [2] + ADB == ADC [2] + ABD == [0] 辺 0 : ['AB', 'BC', 'CD'] 辺の和 三角形 ABD : [BAD, AB[0], ABD, BD, ADB, AD] BCD : [CBD[2], BC[0], BCD[1], CD[0], BDC[2], BD]
よく見たら、一番上の結果だけ見れば良いのか。新しく作図したBD自体についてしか明らかになっていないので、この作図は少なくともこのステップでは意味が無かった。
で、点と点の分だけ辺を延長だけど、それをすることで新しく三角形が発生するということが無いので、スルーする。機械的に三角形が発生しているか調べる時は、その作図をすることで新しく生まれる点に着目して三角形を探せば良いと思う。
で、次に二等辺三角形の作図だけど、二等分線以外のパターンも考えられるな。ABと同じ長さの辺を点BからADの上に作図する、というのもあっても良いのではないか。
というか、例えば二等分線がどこと交わるか、分からないんだよな。でも、今の所は、作図はあくまでアナログというか、人間がやるような論理的ではない別工程なのだし、長くなるけどやってみるか。
まず辺ABに着目する。
辺ABの二等分線と辺ADの交点で、二等辺三角形を作図する場合を考えてみる。
交点をEとする。
triangle_lst = {
"ABE" : ["BAE", "AB", "ABE", "BE", "AEB", "AE"]
}
angle_equ = {
168 : 0,
"ABC" : 0,
108 : 1,
"BCD" : 1,
"BAE" : 2,
"ABE" : 2
}
side_equ = {
"AB" : 0,
"BC" : 0,
"CD" : 0,
"AE" : 1,
"BE" : 1
}
sum_angle_lst = [
["AEB", "BED", 180],
["ABE", "CBE", 168]
]
sum_side_lst = [
["AE", "DE", "AD"]
]
角 0 : [168, 'ABC'] 1 : [108, 'BCD'] 2 : ['BAE', 'ABE'] 角の和 AEB + BED == 180 [2] + CBE == [0] 辺 0 : ['AB', 'BC', 'CD'] 1 : ['AE', 'BE'] 辺の和 [1] + DE == AD 三角形 ABE : [BAE[2], AB[0], ABE[2], BE[1], AEB, AE[1]]
ってそうか、三角形が2つは無いと駄目なのか。
じゃあ、次はBCの上に二等辺三角形でも作ってみるか。
triangle_lst = {
"ABE" : ["BAE", "AB", "ABE", "BE", "AEB", "AE"],
"BCE" : ["CBE", "BC", "BCE", "CE", "BEC", "BE"],
"CDE" : ["DCE", "CD", "CDE", "DE", "CED", "CE"]
}
angle_equ = {
168 : 0,
"ABC" : 0,
108 : 1,
"BCD" : 1,
"CBE" : 2,
"BCE" : 2
}
side_equ = {
"AB" : 0,
"BC" : 0,
"CD" : 0,
"BE" : 1,
"CE" : 1
}
sum_angle_lst = [
["ABE", "CBE", "ABC"],
["BCE", "DCE", "BCD"],
["AEB", "BEC", "AEC"],
["BEC", "CED", "BED"],
["AEC", "CED", 180],
["BED", "AEB", 180]
]
sum_side_lst = [
["AE", "DE", "AD"]
]
角 0 : [168, 'ABC'] 1 : [108, 'BCD'] 2 : ['CBE', 'BCE'] 角の和 AEC + CED == 180 BED + AEB == 180 AEB + BEC == AEC BEC + CED == BED [2] + ABE == [0] [2] + DCE == [1] 辺 0 : ['AB', 'BC', 'CD'] 1 : ['BE', 'CE'] 辺の和 AE + DE == AD 三角形 ABE : [BAE, AB[0], ABE, BE[1], AEB, AE] BCE : [CBE[2], BC[0], BCE[2], CE[1], BEC, BE[1]] CDE : [DCE, CD[0], CDE, DE, CED, CE[1]]
何にも無いな。本当にこれで良いのかね。
同じ三角形の作図。と書いたけど、同じ図形の作図だな。同じ長さの辺の上に作図する。
まずBCを底辺として、そのまま左右に反転させた図形。新しい点Dだった点をE、点Aだった点をF。更に辺CDだった辺とADの交点をG、辺ADだった辺と辺ADをH、辺ADだった辺と辺CDの交点をIとする。(手元に書いた)
triangle_lst = {
"ABG" : ["BAG", "AB", "ABG", "BG", "AGB", "AG"],
"EGH" : ["GEH", "EG", "EGH", "GH", "EHG", "EH"],
"DHI" : ["HDI", "DH", "DHI", "HI", "DIH", "DI"],
"CFI" : ["FCI", "CF", "CFI", "FI", "CIF", "CI"]
}
定義と、あと対頂角も登録しないとな。並行もありそうだけど、角度から並行を見つける機能も必要かな?
angle_equ = {
168 : 0,
"ABC" : 0,
"BCF" : 0,
108 : 1,
"BCI" : 1,
"CBG" : 1,
"BAG" : 2,
"CFI" : 2,
"GEH" : 3,
"HDI" : 3,
"AGB" : 4,
"EGH" : 4,
"AGE" : 5,
"BGH" : 5,
"CIF" : 6,
"DIH" : 6,
"CIH" : 7,
"DIF" : 7,
"GHI" : 8,
"DHE" : 8,
"EHG" : 9,
"DHI" : 9
}
side_equ = {
"AB" : 0,
"BC" : 0,
"CD" : 0,
"CF" : 0,
"BE" : 0,
"AD" : 1,
"EF" : 1
}
じゃあ点に着目して、角の和を見つけていくかな。
sum_angle_lst = [
["ABG", "CBG", "ABC"],
["BCI", "FCI", "BCF"],
["AGB", "BGH", 180],
["GHI", "DHI", 180],
["CIH", "CIF", 180]
]
辺の和はどうやって見つけようかな。やっぱり点に着目していくかな。
sum_side_lst = [
["BG", "EG", "BE"],
["AG", "GH", "AH"],
["AG", "DG", "AD"],
["GH", "DH", "DG"],
["AH", "DH", "AD"],
["EH", "HI", "EI"],
["EH", "FH", "EF"],
["CI", "DI", "CD"],
["HI", "FI", "FH"],
["FI", "EI", "EF"]
]
いやちょっと、なんだこれって感じだけど。三角形定理ループプログラムを回してみる。
angle_equ[4] == angle_equ[6] FCI == ABG BG == CI AG == FI angle_equ[5] == angle_equ[7] EG == DI DG == EI GH == HI EH == DH AH == FH 角 0 : [168, 'ABC', 'BCF'] 1 : [108, 'BCI', 'CBG'] 2 : ['BAG', 'CFI'] 3 : ['GEH', 'HDI'] 4 : ['AGB', 'EGH', 'CIF', 'DIH'] 5 : ['AGE', 'BGH', 'CIH', 'DIF'] 8 : ['GHI', 'DHE'] 9 : ['EHG', 'DHI'] 10 : ['FCI', 'ABG'] 角の和 [4] + [5] == 180 [8] + [9] == 180 [1] + [10] == [0] 辺 0 : ['AB', 'BC', 'CD', 'CF', 'BE'] 1 : ['AD', 'EF'] 2 : ['BG', 'CI'] 3 : ['AG', 'FI'] 4 : ['EG', 'DI'] 5 : ['DG', 'EI'] 6 : ['GH', 'HI'] 7 : ['EH', 'DH'] 8 : ['AH', 'FH'] 辺の和 [2] + [4] == [0] [7] + [8] == [1] [3] + [5] == [1] [6] + [7] == [5] [3] + [6] == [8] 三角形 ABG : [BAG[2], AB[0], ABG[10], BG[2], AGB[4], AG[3]] EGH : [GEH[3], EG[4], EGH[4], GH[6], EHG[9], EH[7]] DHI : [HDI[3], DH[7], DHI[9], HI[6], DIH[4], DI[4]] CFI : [FCI[10], CF[0], CFI[2], FI[3], CIF[4], CI[2]]
結局、分かりにくいけど、角AがBAGで[2]、角DがHDIで[3]、角Bが168の[0]で、角Cが108の[1]なんで、何も分かってないと言える。
これちょっとどうしようかな。まあ、1ステップだけ全部やるか。作図がどんな感じか分からないと、自動化することもできない。
順番がゴチャゴチャな気もするけど、次はABとBCを入れ替えるような作図をやってみようか。
手元で描いてみた。どの辺とどの辺で交点ができるか分からないっていうのが、プログラムを作る上での壁なんだよな。なぜ、ADだった辺とADはクロスするのだろう。ABCDというクラスタがあって、その外側からアクセスしているから?、いや違うな。ABやBCではあり得ず、また点Cを端にしているという点でCDでもあり得ないから?、いや包み込むような場合があり得るな。点Cに対しては角度が浅く、点Aに対しては角度が大きいから?、あり得るような気もする。図形と図形なら、そういう考え方ができる場合もあるか?、でも共有していない場合も交点が発生する場合はあり得る。
これは小学生が現に解いている問題なわけで、必ず論理的な答えはあるはず。そうでなければ部分的には出題者のミスとして言い切れるはず。そのどちらかは分かるはずだと思っているが。
この作図に限っては、2つの辺のどちらで交点が発生するかは言い切れる。そういう交点の判断例を集めることが重要かと思う。
では、新しく追加した点Dだった点をE、新しい交点をFと名付ける。
AE上の点と、CE上の点に着目して三角形を探す。
triangle_lst = {
"AEF" : ["EAF", "AE", "AEF", "EF", "AFE", "AF"],
"CDF" : ["DCF", "CD", "CDF", "DF", "CFD", "CF"]
}
コピー元の定義と(忘れていたけどコピー元との対応と)、対頂角と平行線の同位角と錯角を記載する。あと、角の名前を修正する。
angle_equ = {
168 : 0,
"ABC" : 0,
108 : 1,
"BCD" : 1,
"BAE" : 1,
"AFE" : 2,
"CFD" : 2,
"AFC" : 3,
"DFE" : 3,
"AEF" : 4,
"CDF" : 4,
"BAF" : 5,
"BCF" : 5
}
side_equ = {
"AB" : 0,
"BC" : 0,
"CD" : 0,
"AE" : 0,
"AD" : 1,
"CE" : 1
}
点に着目して単純な角の和と、三角形に着目して外角の性質による角の和を記載する。
sum_angle_lst = [
["BAF", "EAF", "BAE"],
["BCF", "DCF", "BCD"],
["AFE", "AFC", 180],
["EAF", "AEF", "AFC"],
["DCF", "CDF", "AFC"]
]
点あるいは点から伸びている辺に着目して、辺の和を記載する。
sum_side_lst = [
["CF", "EF", "CE"],
["AF", "DF", "AD"]
]
三角形定理ループプログラムを回す。
EAF == DCF EF == DF AF == CF 角 0 : [168, 'ABC'] 1 : [108, 'BCD', 'BAE'] 2 : ['AFE', 'CFD'] 3 : ['AFC', 'DFE'] 4 : ['AEF', 'CDF'] 5 : ['BAF', 'BCF'] 6 : ['EAF', 'DCF'] 角の和 [2] + [3] == 180 [5] + [6] == [1] [4] + [6] == [3] 辺 0 : ['AB', 'BC', 'CD', 'AE'] 1 : ['AD', 'CE'] 2 : ['EF', 'DF'] 3 : ['AF', 'CF'] 辺の和 [2] + [3] == [1] 三角形 AEF : [EAF[6], AE[0], AEF[4], EF[2], AFE[2], AF[3]] CDF : [DCF[6], CD[0], CDF[4], DF[2], CFD[2], CF[3]]
新しく明らかになったものが無かったので、意味無し。でも、やっぱり論点はどの辺とどの辺で交点ができるかの判定だと思う。
似たようなパターンで、BCとCDで入れ替えてみる。気付いたけど、同じ長さの辺と辺の関係を考えれば、つまり例えばBCを全部考えたら、残りの辺ではBCについて考える必要は無さそうだ。
交点の判定も似たようなパターンで、共有した2点の角度が互い違いで交点が発生することは確定し、しかも2辺なのでどちらの辺で発生するのかも確定する。
新しい元AをE、元ADとADで発生する交点をFとする。
新しく追加した辺BE・辺DE上の点に着目して三角形を探していく。
triangle_lst = {
"ABF" : ["BAF", "AB", "ABF", "BF", "AFB", "AF"],
"DEF" : ["EDF", "DE", "DEF", "EF", "DFE", "DF"]
}
対応する角や辺と、対頂角と、平行線の同位角と錯角を登録していく。角の名前も修正する。
angle_equ = {
168 : 0,
"ABC" : 0,
"CDE" : 0,
108 : 1,
"BCD" : 1,
"BAF" : 2,
"DEF" : 2,
"CDF" : 3,
"CBF" : 3,
"AFB" : 4,
"DFE" : 4,
"BFD" : 5,
"AFE" : 5
}
side_equ = {
"AB" : 0,
"BC" : 0,
"CD" : 0,
"DE" : 0,
"AD" : 1,
"BE" : 1
}
新しく追加した辺BE・辺DE上の点に着目して、新しい角の和を探していく。また三角形に着目して外角の法則による角の和を探していく。
sum_angle_lst = [
["ABF", "CBF", "ABC"],
["CDF", "EDF", "CDE"],
["AFB", "BFD", 180],
["BAF", "ABF", "BFD"],
["EDF", "DEF", "BFD"]
]
で辺の和だけど、角の和で180°が見つかった、"AFB"と"BFD"の要であるFについてだけ探せば良いのではないか。まあどうでも良い話ではあるけども。
sum_side_lst = [
["AF", "DF", "AD"],
["BF", "EF", "BE"]
]
三角形定理ループプログラムを回してみる。
ABF == EDF BF == DF AF == EF 角 0 : [168, 'ABC', 'CDE'] 1 : [108, 'BCD'] 2 : ['BAF', 'DEF'] 3 : ['CDF', 'CBF'] 4 : ['AFB', 'DFE'] 5 : ['BFD', 'AFE'] 6 : ['ABF', 'EDF'] 角の和 [4] + [5] == 180 [3] + [6] == [0] [2] + [6] == [5] 辺 0 : ['AB', 'BC', 'CD', 'DE'] 1 : ['AD', 'BE'] 2 : ['BF', 'DF'] 3 : ['AF', 'EF'] 辺の和 [2] + [3] == [1] 三角形 ABF : [BAF[2], AB[0], ABF[6], BF[2], AFB[4], AF[3]] DEF : [EDF[6], DE[0], DEF[2], EF[3], DFE[4], DF[2]]
実は一回ミスをして妙な結果になったんだが、まあ修正した。何も無し。
次はBCをCDに反転させずに重ねるような作図を考えてみる。
角Bと角Cだと角Bの方が大きく、また角Cと角Dでも角Cの方が大きい(なぜなら四角形は内角が360°で残りは84°しか無いから)。
この場合は、交点は2つか0かのどちらかだろう。直感的には、元ADがABとBCのどちらに交わるかが特に分からない。
困ったなあ。というかこれ、五角形とか六角形とかだったらどうするんだろう。
一つの方法としては、交点がどこで発生するか分からない場合は、そもそも交点を考えないというのがある。その場合、その交点による三角形や、角の和や辺の和などは作られない。おそらくだが、その場合でも問題無く三角形定理ループは回せる。しかし、その方法を取るならば、だからこそどの場合にどの辺と辺で交点が発生するのかを明らかにしなければならない。
暫定的に、分からない、としてみようか。それで問題が出るまで待つことにしよう。おそらく、三角関数(直角の場合しか憶えてないが、多分そういうものがある)のようなものが必要になるのではないかと思うが。その場合は、その関数がどういう風に導かれるかが問題になる。
分からないものは交点を考えないとして、少なくとも2つ以上三角形は生まれないので、この場合は考えない。
よく考えたら、交点の検討こそがメインであって、その後の対応する角や辺の登録だとか、三角形を探したりするのだとかは、もはやオマケでしかないのではないか。
順番が滅茶苦茶だけど、次はBCをABにそのままズラしたような作図を検討する。
角Bの方が角Aより大きく、逆に角Cは角Bより小さいので、おそらく交わる回数は1回か3回だろう。手元で描いてみたら、3回交わったら、三角形が4つできることもありそうだが。
元のADに交わるとは限らない、例えばBCとADを縮めれば、元CDと新しいCDで交わることもあり得るし、元ADと新しいCDもあり得る。元CDと新しいADだけというのは無理だろうが。
元AD 新しいAD ○
元AD 新しいCD ○
元CD 新しいAD ×
元CD 新しいCD ○
元AD 新しいADとCD ×
元CD 新しいADとCD 更にその場合は元ADと新しいAD ○
いやだからどうしたという話で、ちょっと迷走しているな。
とにかく、絶対にどこかの辺に交点ができるということは無いということじゃないか。
まあ別に、交点が分からないから交点を加えないとして、今のところは解答のプロセスには影響は無い。
3辺以上になると、角度が完全に内側にあっても外側にあっても、互い違いになっていても、分からないということが分かったんじゃないか。
補助線を引いて三角形にしたりして考えてみても、どうも何かの条件で、どの辺とどの辺で交点が発生するかを特定するのは難しいのではないか。いや分からないが。
2辺以内という条件で、支障が出るのを待つか。
うーん、3つの辺なら、一方の対角線と、もう一方の逆側の普通の線で、交わったら、とかそういう条件はどうだろう。対角線と交わった場合、対角線側を形作るどちらか1辺と交わっている、とか。
更にその対角線側のどちらの辺と交わっているかも、反対の対角線と、その普通の線で角度を比べて、浅いか深いかみたいな。
いや、交わらない場合が判定できないのではないか。いや、しかしそれも、もう一方でも調べて照らし合わせれば良いか?
いやいやいや、そもそも交わるかが分からないからな。
いや考えてみても、やっぱりちょっと無理だな。
やっぱりとりあえず2辺以内だったら、互い違いかを見ることで、辺が交わるか、そしてどちらの辺と辺が交わるかが分かる、という所に留めておくべきではないか。支障が出た時に、その問題ではどう考えているかを見れば良い。
ということは、ABとCDを合わせるのは、お互いに3辺同士だから、どの辺に交点ができるかは分からないということになるのか?
ADを左右に反転させるのも、3辺同士だから、どの辺に交点ができるかは分からない?
まあ確かにこの問題では支障は無いが。しかしどこかで支障が出そうな気はするな。いやその時は答えを見て、その論理をそのままパクれば良いのか。でも多分、三角形の形が確定した後に、あの表みたいなのを見るのが正解なんだと思うなあ。
一番の問題である、作図した時に辺と辺の交点がどこにできるか問題は、とりあえず「3辺以上だったら交点は考えない」で良いか。
まあでも作業の流れをハッキリさせる必要があるんで、このまま2ステップ目に進むか。
三角形定理ループだとかの自動化
できた。
テストツールを導入するほどでも無いと思ったんで、テストは手元でごく簡単に済ませた。
明日1日休んで、明後日から2ステップの作図の問題を解こう。
まあ細かい修正は必要だろうが。
プログラムの上の方で実行したかったのだけど、関数が定義されてないだとかでエラーが出てできないんだね。できると思ってた。
当たり前だけどプログラムは読まない方が良い。結果を先に上の方に貼っておく。
angle_equ[4] == angle_equ[0] angle_equ[7] == DCG AC == CE angle_equ[6] == angle_equ[7] angle_equ[8] == angle_equ[9] AH == DH side_equ[0] == DI BE == EI side_equ[2] == DE CH == EH angle_equ[1] == angle_equ[5] DCF == angle_equ[1] side_equ[4] == DG 角 0 : ['DAI', 'BCD', 'FEI', 'FCG', 'EBI', 'CGD', 'AIH', 'BIE', 'CDG'] 1 : ['ADC', 'CBI', 'CFE', 'CGH', 'AIE', 'BIH', 'DCF'] 2 : ['AHG', 'CHI'] 3 : ['AHI', 'CHG', 'FCH'] 6 : ['DAH', 'BCH', 'ADG', 'BEI', 'BCF', 'DCG'] 8 : ['HAI', 'DCH', 'BEF', 'BCG'] 角の和 [2] + [3] == 180 [0] + [1] == 180 [3] + GCH == [0] [6] + [8] == [0] [0] + [6] == [1] [3] + [8] == [1] [1] + GCH == [2] [0] + [8] == [2] [6] + [6] == [3] [6] + GCH == [8] 辺 0 : ['AD', 'BC', 'EG', 'CF', 'DI'] 1 : ['AB', 'CD', 'EF', 'CG'] 2 : ['AC', 'CE', 'DE'] 3 : ['AH', 'DH'] 4 : ['BE', 'EI', 'DG'] 5 : ['CH', 'EH'] 辺の和 GH + HI == GI [5] + GH == [0] [3] + HI == [0] [4] + GI == [0] AI + BI == [1] [3] + [5] == [2] [0] + [4] == [2] [4] + GH == [3] [4] + HI == [5] 三角形 ABC : [HAI[8], AB[1], CBI[1], BC[0], BCH[6], AC[2]] ACD : [DAH[6], AC[2], DCH[8], CD[1], ADC[1], AD[0]] ADH : [DAH[6], AD[0], ADG[6], DH[3], AHG[2], AH[3]] ADI : [DAI[0], AD[0], ADG[6], DI[0], AIH[0], AI] AHI : [HAI[8], AH[3], AHI[3], HI, AIH[0], AI] BEI : [EBI[0], BE[4], BEI[6], EI[4], BIE[0], BI] CDE : [BCD[0], CD[1], CDG[0], DE[2], BEI[6], CE[2]] CDG : [DCG[6], CD[1], CDG[0], DG[4], CGD[0], CG[1]] CDH : [DCH[8], CD[1], CDG[0], DH[3], CHG[3], CH[5]] CEF : [BCF[6], CE[2], BEF[8], EF[1], CFE[1], CF[0]] CEG : [BCG[8], CE[2], BEI[6], EG[0], CGH[1], CG[1]] CEH : [BCH[6], CE[2], BEI[6], EH[5], CHI[2], CH[5]] CGH : [GCH, CG[1], CGH[1], GH, CHG[3], CH[5]]
import itertools triangle_lst = { "ABC" : ["HAI", "AB", "CBI", "BC", "BCH", "AC"], "ACD" : ["DAH", "AC", "DCH", "CD", "ADC", "AD"], "ADH" : ["DAH", "AD", "ADG", "DH", "AHG", "AH"], "ADI" : ["DAI", "AD", "ADG", "DI", "AIH", "AI"], "AHI" : ["HAI", "AH", "AHI", "HI", "AIH", "AI"], "BEI" : ["EBI", "BE", "BEI", "EI", "BIE", "BI"], "CDE" : ["BCD", "CD", "CDG", "DE", "BEI", "CE"], "CDG" : ["DCG", "CD", "CDG", "DG", "CGD", "CG"], "CDH" : ["DCH", "CD", "CDG", "DH", "CHG", "CH"], "CEF" : ["BCF", "CE", "BEF", "EF", "CFE", "CF"], "CEG" : ["BCG", "CE", "BEI", "EG", "CGH", "CG"], "CEH" : ["BCH", "CE", "BEI", "EH", "CHI", "CH"], "CGH" : ["GCH", "CG", "CGH", "GH", "CHG", "CH"], } side_equ = { "AD" : 0, "BC" : 0, "EG" : 0, "CF" : 0, "AB" : 1, "CD" : 1, "EF" : 1, "CG" : 1 } angle_equ = { "DAI" : 0, "BCD" : 0, "FEI" : 0, "FCG" : 0, "EBI" : 0, "CGD" : 0, "ADC" : 1, "CBI" : 1, "CFE" : 1, "CGH" : 1, "AHG" : 2, "CHI" : 2, "AHI" : 3, "CHG" : 3, "FCH" : 3, "AIH" : 4, "BIE" : 4, "CDG" : 4, "AIE" : 5, "BIH" : 5, "DAH" : 6, "BCH" : 6, "ADG" : 7, "BEI" : 7, "BCF" : 7, "HAI" : 8, "DCH" : 8, "BEF" : 9, "BCG" : 9, } sum_angle_lst = [ #[0] + [1] = [2] ["DAH", "HAI", "DAI"], ["EBI", "CBI", 180], ["DCG", "GCH", "DCH"], ["GCH", "BCH", "BCG"], ["BCH", "BCF", "FCH"], ["DCH", "BCH", "BCD"], ["BCG", "DCG", "BCD"], ["BCG", "BCF", "FCG"], ["FCH", "GCH", "FCG"], ["BCD", "BCF", "DCF"], ["FCG", "DCG", "DCF"], ["ADG", "CDG", "ADC"], ["BEI", "BEF", "FEI"], ["CGD", "CGH", 180], ["AHG", "CHG", 180], ["AIH", "AIE", 180], ["HAI", "BCH", "EBI"], ["BCG", "BEI", "CGD"], ["DAH", "ADG", "AHI"], ["DAI", "ADG", "AIE"], ["DCG", "CDG", "CGH"], ["EBI", "BEI", "BIH"], ["BEI", "BIE", "CBI"], ["HAI", "AHI", "BIH"], ["HAI", "AIH", "AHG"], ["DCH", "CDG", "AHG"], ["GCH", "CGH", "CHI"], ["GCH", "CHG", "CGD"] ] sum_side_lst = [ #[0] + [1] = [2] ["AI", "BI", "AB"], ["AH", "CH", "AC"], ["BC", "BE", "CE"], ["DG", "EG", "DE"], ["DH", "EH", "DE"], ["DI", "EI", "DE"], ["DG", "GH", "DH"], ["DG", "GI", "DI"], ["DH", "HI", "DI"], ["EI", "GI", "EG"], ["EH", "GH", "EG"], ["EI", "HI", "EH"], ["GH", "HI", "GI"] ] def angle1_equal_angle2(angle_equ, angle1, angle2): if angle1 not in angle_equ and angle2 not in angle_equ: angle_equ_values = list(angle_equ.values()) if angle_equ_values != []: max_value = max(angle_equ_values) new_value = max_value + 1 else: new_value = 0 angle_equ[angle1] = new_value angle_equ[angle2] = new_value elif angle1 in angle_equ and angle2 not in angle_equ: angle_equ[angle2] = angle_equ[angle1] elif angle1 not in angle_equ and angle2 in angle_equ: angle_equ[angle1] = angle_equ[angle2] elif angle_equ[angle1] > angle_equ[angle2]: big_value = angle_equ[angle1] #束縛は大丈夫? small_value = angle_equ[angle2] for k, v in angle_equ.items(): if v == big_value: angle_equ[k] = small_value elif angle_equ[angle1] < angle_equ[angle2]: big_value = angle_equ[angle2] small_value = angle_equ[angle1] for k, v in angle_equ.items(): if v == big_value: angle_equ[k] = small_value return angle_equ """ #angle_equ = angle1_equal_angle2(angle_equ, "CDG", "CGD") #angle_equの中に、有る 有る #angle_equ = angle1_equal_angle2(angle_equ, "CDG", "GCH") #有る 無い #angle_equ = angle1_equal_angle2(angle_equ, "GCH", "CGD") #無い 有る #angle_equ = angle1_equal_angle2(angle_equ, "GCH", "DCG") #無い 無い print(angle_equ) """ def side1_equal_side2(side_equ, side1, side2): if side1 not in side_equ and side2 not in side_equ: side_equ_values = list(side_equ.values()) if side_equ_values != []: max_value = max(side_equ_values) new_value = max_value + 1 else: new_value = 0 side_equ[side1] = new_value side_equ[side2] = new_value elif side1 in side_equ and side2 not in side_equ: side_equ[side2] = side_equ[side1] elif side1 not in side_equ and side2 in side_equ: side_equ[side1] = side_equ[side2] elif side_equ[side1] > side_equ[side2]: big_value = side_equ[side1] #束縛は大丈夫? small_value = side_equ[side2] for k, v in side_equ.items(): if v == big_value: side_equ[k] = small_value elif side_equ[side1] < side_equ[side2]: big_value = side_equ[side2] small_value = side_equ[side1] for k, v in side_equ.items(): if v == big_value: side_equ[k] = small_value return side_equ """ #side_equ = side1_equal_side2(side_equ, "AD", "AB") #side_equの中に、有る 有る #side_equ = side1_equal_side2(side_equ, "AD", "AH") #有る 無い #side_equ = side1_equal_side2(side_equ, "AH", "AD") #無い 有る #side_equ = side1_equal_side2(side_equ, "AH", "BE") #無い 無い print(side_equ) """ #いろいろやる関数。既にイコールかを確認して、そうでなければ新しいイコールとしてprint関数で出力して、新しいイコールとして登録して、内側のwhile文用のloop_flgと実行したことを伝えるexe_flgをTrueにして返す。 def equ_angle_sub(angle_equ, angle1, angle2, loop_flg, exe_flg): if not (angle1 == angle2 or (angle1 in angle_equ and angle2 in angle_equ and angle_equ[angle1] == angle_equ[angle2])): angle1_val = "angle_equ[" + str(angle_equ[angle1]) + "]" if angle1 in angle_equ else angle1 angle2_val = "angle_equ[" + str(angle_equ[angle2]) + "]" if angle2 in angle_equ else angle2 print(str(angle1_val) + " == " + str(angle2_val)) angle_equ = angle1_equal_angle2(angle_equ, angle1, angle2) loop_flg = True exe_flg = True return angle_equ, loop_flg, exe_flg #一つ上の辺バージョン def equ_side_sub(side_equ, side1, side2, loop_flg, exe_flg): if not (side1 == side2 or (side1 in side_equ and side2 in side_equ and side_equ[side1] == side_equ[side2])): side1_val = "side_equ[" + str(side_equ[side1]) + "]" if side1 in side_equ else side1 side2_val = "side_equ[" + str(side_equ[side2]) + "]" if side2 in side_equ else side2 print(str(side1_val) + " == " + str(side2_val)) side_equ = side1_equal_side2(side_equ, side1, side2) loop_flg = True exe_flg = True return side_equ, loop_flg, exe_flg def isosceles_angle_check(triangle_lst, angle_equ, side_equ, exe_flg): loop_flg = True while loop_flg: loop_flg = False for tri1 in triangle_lst.values(): for angle1, angle2, side1, side2 in [(tri1[0], tri1[2], tri1[5], tri1[3]), (tri1[2], tri1[4], tri1[1], tri1[5]), (tri1[0], tri1[4], tri1[1], tri1[3])]: if (angle1 in angle_equ and angle2 in angle_equ and angle_equ[angle1] == angle_equ[angle2]) or (angle1 not in angle_equ and angle2 not in angle_equ and angle1 == angle2): side_equ, loop_flg, exe_flg = equ_side_sub(side_equ, side1, side2, loop_flg, exe_flg) return triangle_lst, angle_equ, side_equ, exe_flg """ triangle_lst = {"TST" : ["ANGLE1", "SIDE1", "ANGLE2", "SIDE2", "ANGLE3", "SIDE3"]} angle_equ = {} side_equ = {} ###テスト1 #angle_equ["ANGLE1"] = 0 #angle_equ["ANGLE2"] = 0 ###テスト2 #triangle_lst["TST"][2] = "ANGLE1" ###テスト3 #angle_equ["ANGLE1"] = 0 #angle_equ["ANGLE2"] = 0 #side_equ["SIDE2"] = 0 #side_equ["SIDE3"] = 0 exe_flg = False triangle_lst, angle_equ, side_equ, exe_flg = isosceles_angle_check(triangle_lst, angle_equ, side_equ, exe_flg) print(exe_flg) print(side_equ) """ def isosceles_side_check(triangle_lst, angle_equ, side_equ, exe_flg): loop_flg = True while loop_flg: loop_flg = False for tri1 in triangle_lst.values(): for side1, side2, angle1, angle2 in [(tri1[1], tri1[3], tri1[0], tri1[4]), (tri1[3], tri1[5], tri1[2], tri1[0]), (tri1[1], tri1[5], tri1[2], tri1[4])]: if (side1 in side_equ and side2 in side_equ and side_equ[side1] == side_equ[side2]) or (side1 not in side_equ and side2 not in side_equ and side1 == side2): angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle1, angle2, loop_flg, exe_flg) return triangle_lst, angle_equ, side_equ, exe_flg """ triangle_lst = {"TST" : ["ANGLE1", "SIDE1", "ANGLE2", "SIDE2", "ANGLE3", "SIDE3"]} angle_equ = {} side_equ = {} ###テスト1 #side_equ["SIDE1"] = 0 #side_equ["SIDE2"] = 0 ###テスト2 #triangle_lst["TST"][3] = "SIDE1" ###テスト3 #side_equ["SIDE1"] = 0 #side_equ["SIDE2"] = 0 #angle_equ["ANGLE3"] = 0 #angle_equ["ANGLE1"] = 0 exe_flg = False triangle_lst, angle_equ, side_equ, exe_flg = isosceles_side_check(triangle_lst, angle_equ, side_equ, exe_flg) print(exe_flg) print(angle_equ) """ def two_angle_check(triangle_lst, angle_equ, side_equ, exe_flg): loop_flg = True while loop_flg: loop_flg = False for tri1 in triangle_lst.values(): for tri2 in triangle_lst.values(): if tri1 == tri2: continue for angle_1_A, angle_1_B in itertools.combinations([tri1[0], tri1[2], tri1[4]], 2): for angle_2_A, angle_2_B in itertools.combinations([tri2[0], tri2[2], tri2[4]], 2): angle_1_A_val = angle_equ[angle_1_A] if angle_1_A in angle_equ else angle_1_A angle_1_B_val = angle_equ[angle_1_B] if angle_1_B in angle_equ else angle_1_B angle_2_A_val = angle_equ[angle_2_A] if angle_2_A in angle_equ else angle_2_A angle_2_B_val = angle_equ[angle_2_B] if angle_2_B in angle_equ else angle_2_B if {angle_1_A_val, angle_1_B_val} == {angle_2_A_val, angle_2_B_val}: angle_1_C = [A for A in [tri1[0], tri1[2], tri1[4]] if A not in [angle_1_A, angle_1_B]][0] angle_2_C = [A for A in [tri2[0], tri2[2], tri2[4]] if A not in [angle_2_A, angle_2_B]][0] angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_C, angle_2_C, loop_flg, exe_flg) return triangle_lst, angle_equ, side_equ, exe_flg """ triangle_lst = { "TST1" : ["ANGLE1", "SIDE1", "ANGLE2", "SIDE2", "ANGLE3", "SIDE3"], "TST2" : ["ANGLE4", "SIDE4", "ANGLE5", "SIDE5", "ANGLE6", "SIDE6"] } angle_equ = {} side_equ = {} ###テスト1 #angle_equ["ANGLE1"] = 0 #angle_equ["ANGLE4"] = 0 #angle_equ["ANGLE2"] = 1 #angle_equ["ANGLE5"] = 1 ###テスト2 #triangle_lst["TST2"][0] = "ANGLE1" #triangle_lst["TST2"][2] = "ANGLE2" ###テスト3 #triangle_lst["TST2"][0] = "ANGLE1" #angle_equ["ANGLE2"] = 0 #angle_equ["ANGLE5"] = 0 ###テスト4 #angle_equ["ANGLE1"] = 0 #angle_equ["ANGLE4"] = 0 #angle_equ["ANGLE2"] = 1 #angle_equ["ANGLE5"] = 1 #angle_equ["ANGLE3"] = 2 #angle_equ["ANGLE6"] = 2 exe_flg = False triangle_lst, angle_equ, side_equ, exe_flg = two_angle_check(triangle_lst, angle_equ, side_equ, exe_flg) print(exe_flg) print(angle_equ) """ def angle_side_angle(triangle_lst, angle_equ, side_equ, exe_flg): loop_flg = True while loop_flg: loop_flg = False for tri1 in triangle_lst.values(): for tri2 in triangle_lst.values(): if tri1 == tri2: continue for angle_1_A, side_1, angle_1_B, side_1_X, angle_1_C, side_1_Y in [(tri1[0], tri1[1], tri1[2], tri1[3], tri1[4], tri1[5]), \ (tri1[2], tri1[3], tri1[4], tri1[5], tri1[0], tri1[1]), \ (tri1[4], tri1[5], tri1[0], tri1[1], tri1[2], tri1[3])]: for angle_2_A, side_2, angle_2_B, side_2_X, angle_2_C, side_2_Y in [(tri2[0], tri2[1], tri2[2], tri2[3], tri2[4], tri2[5]), \ (tri2[2], tri2[3], tri2[4], tri2[5], tri2[0], tri2[1]), \ (tri2[4], tri2[5], tri2[0], tri2[1], tri2[2], tri2[3])]: angle_1_A_val = angle_equ[angle_1_A] if angle_1_A in angle_equ else angle_1_A side_1_val = side_equ[side_1] if side_1 in side_equ else side_1 angle_1_B_val = angle_equ[angle_1_B] if angle_1_B in angle_equ else angle_1_B angle_2_A_val = angle_equ[angle_2_A] if angle_2_A in angle_equ else angle_2_A side_2_val = side_equ[side_2] if side_2 in side_equ else side_2 angle_2_B_val = angle_equ[angle_2_B] if angle_2_B in angle_equ else angle_2_B if side_1_val == side_2_val and {angle_1_A_val, angle_1_B_val} == {angle_2_A_val, angle_2_B_val}: angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_C, angle_2_C, loop_flg, exe_flg) if angle_1_A_val == angle_2_A_val: side_equ, loop_flg, exe_flg = equ_side_sub(side_equ, side_1_X, side_2_X, loop_flg, exe_flg) side_equ, loop_flg, exe_flg = equ_side_sub(side_equ, side_1_Y, side_2_Y, loop_flg, exe_flg) else: side_equ, loop_flg, exe_flg = equ_side_sub(side_equ, side_1_X, side_2_Y, loop_flg, exe_flg) side_equ, loop_flg, exe_flg = equ_side_sub(side_equ, side_1_Y, side_2_X, loop_flg, exe_flg) return triangle_lst, angle_equ, side_equ, exe_flg """ triangle_lst = { "TST1" : ["ANGLE1", "SIDE1", "ANGLE2", "SIDE2", "ANGLE3", "SIDE3"], "TST2" : ["ANGLE4", "SIDE4", "ANGLE5", "SIDE5", "ANGLE6", "SIDE6"] } angle_equ = {} side_equ = {} ###テスト1 #angle_equ["ANGLE1"] = 0 #angle_equ["ANGLE4"] = 0 #side_equ["SIDE1"] = 0 #side_equ["SIDE4"] = 0 #angle_equ["ANGLE2"] = 1 #angle_equ["ANGLE5"] = 1 ###テスト2 #triangle_lst["TST2"][0] = "ANGLE1" #triangle_lst["TST2"][1] = "SIDE1" #triangle_lst["TST2"][2] = "ANGLE2" ###テスト3 #triangle_lst["TST2"][0] = "ANGLE1" #side_equ["SIDE1"] = 0 #side_equ["SIDE4"] = 0 #angle_equ["ANGLE2"] = 0 #angle_equ["ANGLE5"] = 0 ###テスト4 #angle_equ["ANGLE1"] = 0 #angle_equ["ANGLE4"] = 0 #side_equ["SIDE1"] = 0 #side_equ["SIDE4"] = 0 #angle_equ["ANGLE2"] = 1 #angle_equ["ANGLE5"] = 1 #side_equ["SIDE2"] = 1 #side_equ["SIDE5"] = 1 #angle_equ["ANGLE3"] = 2 #angle_equ["ANGLE6"] = 2 #side_equ["SIDE3"] = 2 #side_equ["SIDE6"] = 2 exe_flg = False triangle_lst, angle_equ, side_equ, exe_flg = angle_side_angle(triangle_lst, angle_equ, side_equ, exe_flg) print(exe_flg) print(angle_equ) print(side_equ) """ def side_angle_side(triangle_lst, angle_equ, side_equ, exe_flg): loop_flg = True while loop_flg: loop_flg = False for tri1 in triangle_lst.values(): for tri2 in triangle_lst.values(): if tri1 == tri2: continue for side_1_A, angle_1, side_1_B, angle_1_X, side_1_C, angle_1_Y in [(tri1[1], tri1[2], tri1[3], tri1[4], tri1[5], tri1[0]), \ (tri1[3], tri1[4], tri1[5], tri1[0], tri1[1], tri1[2]), \ (tri1[5], tri1[0], tri1[1], tri1[2], tri1[3], tri1[4])]: for side_2_A, angle_2, side_2_B, angle_2_X, side_2_C, angle_2_Y in [(tri2[1], tri2[2], tri2[3], tri2[4], tri2[5], tri2[0]), \ (tri2[3], tri2[4], tri2[5], tri2[0], tri2[1], tri2[2]), \ (tri2[5], tri2[0], tri2[1], tri2[2], tri2[3], tri2[4])]: side_1_A_val = side_equ[side_1_A] if side_1_A in side_equ else side_1_A angle_1_val = angle_equ[angle_1] if angle_1 in angle_equ else angle_1 side_1_B_val = side_equ[side_1_B] if side_1_B in side_equ else side_1_B side_2_A_val = side_equ[side_2_A] if side_2_A in side_equ else side_2_A angle_2_val = angle_equ[angle_2] if angle_2 in angle_equ else angle_2 side_2_B_val = side_equ[side_2_B] if side_2_B in side_equ else side_2_B if angle_1_val == angle_2_val and {side_1_A_val, side_1_B_val} == {side_2_A_val, side_2_B_val}: side_equ, loop_flg, exe_flg = equ_side_sub(side_equ, side_1_C, side_2_C, loop_flg, exe_flg) if side_1_A_val == side_2_A_val: angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_X, angle_2_X, loop_flg, exe_flg) angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_Y, angle_2_Y, loop_flg, exe_flg) else: angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_X, angle_2_Y, loop_flg, exe_flg) angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_Y, angle_2_X, loop_flg, exe_flg) return triangle_lst, angle_equ, side_equ, exe_flg """ triangle_lst = { "TST1" : ["ANGLE1", "SIDE1", "ANGLE2", "SIDE2", "ANGLE3", "SIDE3"], "TST2" : ["ANGLE4", "SIDE4", "ANGLE5", "SIDE5", "ANGLE6", "SIDE6"] } angle_equ = {} side_equ = {} ###テスト1 #side_equ["SIDE1"] = 0 #side_equ["SIDE4"] = 0 #angle_equ["ANGLE2"] = 0 #angle_equ["ANGLE5"] = 0 #side_equ["SIDE2"] = 1 #side_equ["SIDE5"] = 1 ###テスト2 #triangle_lst["TST2"][1] = "SIDE1" #triangle_lst["TST2"][2] = "ANGLE2" #triangle_lst["TST2"][3] = "SIDE2" ###テスト3 #triangle_lst["TST2"][1] = "SIDE1" #angle_equ["ANGLE2"] = 0 #angle_equ["ANGLE5"] = 0 #side_equ["SIDE2"] = 0 #side_equ["SIDE5"] = 0 ###テスト4 #side_equ["SIDE1"] = 0 #side_equ["SIDE4"] = 0 #angle_equ["ANGLE2"] = 0 #angle_equ["ANGLE5"] = 0 #side_equ["SIDE2"] = 1 #side_equ["SIDE5"] = 1 #angle_equ["ANGLE3"] = 1 #angle_equ["ANGLE6"] = 1 #side_equ["SIDE3"] = 2 #side_equ["SIDE6"] = 2 #angle_equ["ANGLE1"] = 2 #angle_equ["ANGLE4"] = 2 exe_flg = False triangle_lst, angle_equ, side_equ, exe_flg = side_angle_side(triangle_lst, angle_equ, side_equ, exe_flg) print(exe_flg) print(angle_equ) print(side_equ) """ def side_side_side(triangle_lst, angle_equ, side_equ, exe_flg): loop_flg = True while loop_flg: loop_flg = False for tri1 in triangle_lst.values(): for tri2 in triangle_lst.values(): if tri1 == tri2: continue angle_1_A, side_1_A, angle_1_B, side_1_B, angle_1_C, side_1_C = tri1 angle_2_A, side_2_A, angle_2_B, side_2_B, angle_2_C, side_2_C = tri2 side_1_A_val = side_equ[side_1_A] if side_1_A in side_equ else side_1_A side_1_B_val = side_equ[side_1_B] if side_1_B in side_equ else side_1_B side_1_C_val = side_equ[side_1_C] if side_1_C in side_equ else side_1_C side_2_A_val = side_equ[side_2_A] if side_2_A in side_equ else side_2_A side_2_B_val = side_equ[side_2_B] if side_2_B in side_equ else side_2_B side_2_C_val = side_equ[side_2_C] if side_2_C in side_equ else side_2_C if {side_1_A_val, side_1_B_val, side_1_C_val} == {side_2_A_val, side_2_B_val, side_2_C_val}: if side_1_A_val == side_2_A_val: if side_1_B_val == side_2_B_val: angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_A, angle_2_A, loop_flg, exe_flg) angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_B, angle_2_B, loop_flg, exe_flg) angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_C, angle_2_C, loop_flg, exe_flg) elif side_1_B_val == side_2_C_val: angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_A, angle_2_B, loop_flg, exe_flg) angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_B, angle_2_A, loop_flg, exe_flg) angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_C, angle_2_C, loop_flg, exe_flg) elif side_1_A_val == side_2_B_val: if side_1_B_val == side_2_A_val: angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_A, angle_2_C, loop_flg, exe_flg) angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_B, angle_2_B, loop_flg, exe_flg) angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_C, angle_2_A, loop_flg, exe_flg) elif side_1_B_val == side_2_C_val: angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_A, angle_2_B, loop_flg, exe_flg) angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_B, angle_2_C, loop_flg, exe_flg) angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_C, angle_2_A, loop_flg, exe_flg) elif side_1_A_val == side_2_C_val: if side_1_B_val == side_2_A_val: angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_A, angle_2_C, loop_flg, exe_flg) angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_B, angle_2_A, loop_flg, exe_flg) angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_C, angle_2_B, loop_flg, exe_flg) elif side_1_B_val == side_2_B_val: angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_A, angle_2_A, loop_flg, exe_flg) angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_B, angle_2_C, loop_flg, exe_flg) angle_equ, loop_flg, exe_flg = equ_angle_sub(angle_equ, angle_1_C, angle_2_B, loop_flg, exe_flg) return triangle_lst, angle_equ, side_equ, exe_flg """ triangle_lst = { "TST1" : ["ANGLE1", "SIDE1", "ANGLE2", "SIDE2", "ANGLE3", "SIDE3"], "TST2" : ["ANGLE4", "SIDE4", "ANGLE5", "SIDE5", "ANGLE6", "SIDE6"] } angle_equ = {} side_equ = {} ###テスト1 #side_equ["SIDE1"] = 0 #side_equ["SIDE4"] = 0 #side_equ["SIDE2"] = 1 #side_equ["SIDE5"] = 1 #side_equ["SIDE3"] = 2 #side_equ["SIDE6"] = 2 ###テスト2 #triangle_lst["TST2"][1] = "SIDE1" #triangle_lst["TST2"][3] = "SIDE2" #triangle_lst["TST2"][5] = "SIDE3" ###テスト3 #side_equ["SIDE1"] = 0 #side_equ["SIDE4"] = 0 #side_equ["SIDE2"] = 1 #side_equ["SIDE5"] = 1 #triangle_lst["TST2"][5] = "SIDE3" ###テスト4 #side_equ["SIDE1"] = 0 #side_equ["SIDE4"] = 0 #angle_equ["ANGLE2"] = 0 #angle_equ["ANGLE5"] = 0 #side_equ["SIDE2"] = 1 #side_equ["SIDE5"] = 1 #angle_equ["ANGLE3"] = 1 #angle_equ["ANGLE6"] = 1 #side_equ["SIDE3"] = 2 #side_equ["SIDE6"] = 2 #angle_equ["ANGLE1"] = 2 #angle_equ["ANGLE4"] = 2 exe_flg = False triangle_lst, angle_equ, side_equ, exe_flg = side_side_side(triangle_lst, angle_equ, side_equ, exe_flg) print(exe_flg) print(angle_equ) print(side_equ) """ def sum_angle_check(sum_angle_lst, angle_equ, tri_theorem_flg): loop_flg = True while loop_flg: loop_flg = False for sum_angle_1 in sum_angle_lst: for sum_angle_2 in sum_angle_lst: if sum_angle_1 == sum_angle_2: continue angle_1_X, angle_1_Y, angle_1_sum = sum_angle_1 angle_2_X, angle_2_Y, angle_2_sum = sum_angle_2 angle_1_X_val = angle_equ[angle_1_X] if angle_1_X in angle_equ else angle_1_X angle_1_Y_val = angle_equ[angle_1_Y] if angle_1_Y in angle_equ else angle_1_Y angle_1_sum_val = angle_equ[angle_1_sum] if angle_1_sum in angle_equ else angle_1_sum angle_2_X_val = angle_equ[angle_2_X] if angle_2_X in angle_equ else angle_2_X angle_2_Y_val = angle_equ[angle_2_Y] if angle_2_Y in angle_equ else angle_2_Y angle_2_sum_val = angle_equ[angle_2_sum] if angle_2_sum in angle_equ else angle_2_sum for either_angle_1 in [angle_1_X, angle_1_Y]: for either_angle_2 in [angle_2_X, angle_2_Y]: either_angle_1_val = angle_equ[either_angle_1] if either_angle_1 in angle_equ else either_angle_1 either_angle_2_val = angle_equ[either_angle_2] if either_angle_2 in angle_equ else either_angle_2 if angle_1_sum_val == angle_2_sum_val and either_angle_1_val == either_angle_2_val: another_angle_1 = [A for A in [angle_1_X, angle_1_Y] if A != either_angle_1][0] another_angle_2 = [A for A in [angle_2_X, angle_2_Y] if A != either_angle_2][0] angle_equ, loop_flg, tri_theorem_flg = equ_angle_sub(angle_equ, another_angle_1, another_angle_2, loop_flg, tri_theorem_flg) if {angle_1_X_val, angle_1_Y_val} == {angle_2_X_val, angle_2_Y_val}: angle_equ, loop_flg, tri_theorem_flg = equ_angle_sub(angle_equ, angle_1_sum, angle_2_sum, loop_flg, tri_theorem_flg) return sum_angle_lst, angle_equ, tri_theorem_flg """ sum_angle_lst = [ ["TST1", "TST2", "TST3"], ["TST4", "TST5", "TST6"] ] angle_equ = {} ###テスト1 #angle_equ["TST1"] = 0 #angle_equ["TST4"] = 0 #angle_equ["TST2"] = 1 #angle_equ["TST5"] = 1 ###テスト2 #angle_equ["TST1"] = 0 #angle_equ["TST5"] = 0 #angle_equ["TST3"] = 1 #angle_equ["TST6"] = 1 ###テスト3 #angle_equ["TST1"] = 0 #angle_equ["TST4"] = 0 #sum_angle_lst[1][1] = "TST2" ###テスト4 #angle_equ["TST1"] = 0 #angle_equ["TST5"] = 0 #sum_angle_lst[1][2] = "TST3" ###テスト5 #angle_equ["TST1"] = 0 #angle_equ["TST4"] = 0 #angle_equ["TST2"] = 1 #angle_equ["TST5"] = 1 #angle_equ["TST3"] = 2 #angle_equ["TST6"] = 2 tri_theorem_flg = False sum_angle_lst, angle_equ, tri_theorem_flg = sum_angle_check(sum_angle_lst, angle_equ, tri_theorem_flg) print(tri_theorem_flg) print(angle_equ) """ def sum_side_check(sum_side_lst, side_equ, tri_theorem_flg): loop_flg = True while loop_flg: loop_flg = False for sum_side_1 in sum_side_lst: for sum_side_2 in sum_side_lst: if sum_side_1 == sum_side_2: continue side_1_X, side_1_Y, side_1_sum = sum_side_1 side_2_X, side_2_Y, side_2_sum = sum_side_2 side_1_X_val = side_equ[side_1_X] if side_1_X in side_equ else side_1_X side_1_Y_val = side_equ[side_1_Y] if side_1_Y in side_equ else side_1_Y side_1_sum_val = side_equ[side_1_sum] if side_1_sum in side_equ else side_1_sum side_2_X_val = side_equ[side_2_X] if side_2_X in side_equ else side_2_X side_2_Y_val = side_equ[side_2_Y] if side_2_Y in side_equ else side_2_Y side_2_sum_val = side_equ[side_2_sum] if side_2_sum in side_equ else side_2_sum for either_side_1 in [side_1_X, side_1_Y]: for either_side_2 in [side_2_X, side_2_Y]: either_side_1_val = side_equ[either_side_1] if either_side_1 in side_equ else either_side_1 either_side_2_val = side_equ[either_side_2] if either_side_2 in side_equ else either_side_2 if side_1_sum_val == side_2_sum_val and either_side_1_val == either_side_2_val: another_side_1 = [A for A in [side_1_X, side_1_Y] if A != either_side_1][0] another_side_2 = [A for A in [side_2_X, side_2_Y] if A != either_side_2][0] side_equ, loop_flg, tri_theorem_flg = equ_side_sub(side_equ, another_side_1, another_side_2, loop_flg, tri_theorem_flg) if {side_1_X_val, side_1_Y_val} == {side_2_X_val, side_2_Y_val}: side_equ, loop_flg, tri_theorem_flg = equ_side_sub(side_equ, side_1_sum, side_2_sum, loop_flg, tri_theorem_flg) return sum_side_lst, side_equ, tri_theorem_flg """ sum_side_lst = [ ["TST1", "TST2", "TST3"], ["TST4", "TST5", "TST6"] ] side_equ = {} ###テスト1 #side_equ["TST1"] = 0 #side_equ["TST4"] = 0 #side_equ["TST2"] = 1 #side_equ["TST5"] = 1 ###テスト2 #side_equ["TST1"] = 0 #side_equ["TST5"] = 0 #side_equ["TST3"] = 1 #side_equ["TST6"] = 1 ###テスト3 #side_equ["TST1"] = 0 #side_equ["TST4"] = 0 #sum_side_lst[1][1] = "TST2" ###テスト4 #side_equ["TST1"] = 0 #side_equ["TST5"] = 0 #sum_side_lst[1][2] = "TST3" ###テスト5 #side_equ["TST1"] = 0 #side_equ["TST4"] = 0 #side_equ["TST2"] = 1 #side_equ["TST5"] = 1 #side_equ["TST3"] = 2 #side_equ["TST6"] = 2 tri_theorem_flg = False sum_side_lst, side_equ, tri_theorem_flg = sum_side_check(sum_side_lst, side_equ, tri_theorem_flg) print(tri_theorem_flg) print(side_equ) """ def triangle_theorem_loop(triangle_lst, angle_equ, side_equ): exe_flg = True while exe_flg: exe_flg = False triangle_lst, angle_equ, side_equ, exe_flg = isosceles_angle_check(triangle_lst, angle_equ, side_equ, exe_flg) triangle_lst, angle_equ, side_equ, exe_flg = isosceles_side_check(triangle_lst, angle_equ, side_equ, exe_flg) triangle_lst, angle_equ, side_equ, exe_flg = two_angle_check(triangle_lst, angle_equ, side_equ, exe_flg) triangle_lst, angle_equ, side_equ, exe_flg = angle_side_angle(triangle_lst, angle_equ, side_equ, exe_flg) triangle_lst, angle_equ, side_equ, exe_flg = side_angle_side(triangle_lst, angle_equ, side_equ, exe_flg) triangle_lst, angle_equ, side_equ, exe_flg = side_side_side(triangle_lst, angle_equ, side_equ, exe_flg) return triangle_lst, angle_equ, side_equ tri_theorem_flg = True while tri_theorem_flg: triangle_lst, angle_equ, side_equ = triangle_theorem_loop(triangle_lst, angle_equ, side_equ) tri_theorem_flg = False sum_angle_lst, angle_equ, tri_theorem_flg = sum_angle_check(sum_angle_lst, angle_equ, tri_theorem_flg) sum_side_lst, side_equ, tri_theorem_flg = sum_side_check(sum_side_lst, side_equ, tri_theorem_flg) print() print("角") angle_result_lst = {} for k, v in angle_equ.items(): if v not in angle_result_lst: angle_result_lst[v] = [] angle_result_lst[v].append(k) for k, v in sorted(angle_result_lst.items()): print(str(k) + " : " + str(v)) print() print("角の和") sum_angle_result_lst = [] for angles in sum_angle_lst: angle1, angle2, angle3 = angles angle_formula = ["","",""] if angle1 not in angle_equ and angle2 not in angle_equ: angle_formula[0] = str(angle1) angle_formula[1] = str(angle2) elif angle1 not in angle_equ and angle2 in angle_equ: angle_formula[0] = "[" + str(angle_equ[angle2]) + "]" angle_formula[1] = str(angle1) elif angle1 in angle_equ and angle2 not in angle_equ: angle_formula[0] = "[" + str(angle_equ[angle1]) + "]" angle_formula[1] = str(angle2) elif angle1 in angle_equ and angle2 in angle_equ: if angle_equ[angle1] > angle_equ[angle2]: angle_formula[0] = "[" + str(angle_equ[angle2]) + "]" angle_formula[1] = "[" + str(angle_equ[angle1]) + "]" elif angle_equ[angle1] <= angle_equ[angle2]: angle_formula[0] = "[" + str(angle_equ[angle1]) + "]" angle_formula[1] = "[" + str(angle_equ[angle2]) + "]" if angle3 in angle_equ: angle_formula[2] = "[" + str(angle_equ[angle3]) + "]" else: angle_formula[2] = str(angle3) sum_angle_result_lst.append(angle_formula) sum_angle_result_lst = list(map(list, set(map(tuple, sum_angle_result_lst)))) #二次元配列の重複削除、調べたらこんな方法が出てきた for angle1, angle2, angle3 in sorted(sum_angle_result_lst, key=lambda x: x[2]): print(angle1 + " + " + angle2 + " == " + angle3) print() print("辺") side_result_lst = {} for k, v in side_equ.items(): if v not in side_result_lst: side_result_lst[v] = [] side_result_lst[v].append(k) for k, v in sorted(side_result_lst.items()): print(str(k) + " : " + str(v)) print() print("辺の和") sum_side_result_lst = [] for sides in sum_side_lst: side1, side2, side3 = sides side_formula = ["","",""] if side1 not in side_equ and side2 not in side_equ: side_formula[0] = str(side1) side_formula[1] = str(side2) elif side1 not in side_equ and side2 in side_equ: side_formula[0] = "[" + str(side_equ[side2]) + "]" side_formula[1] = str(side1) elif side1 in side_equ and side2 not in side_equ: side_formula[0] = "[" + str(side_equ[side1]) + "]" side_formula[1] = str(side2) elif side1 in side_equ and side2 in side_equ: if side_equ[side1] > side_equ[side2]: side_formula[0] = "[" + str(side_equ[side2]) + "]" side_formula[1] = "[" + str(side_equ[side1]) + "]" elif side_equ[side1] <= side_equ[side2]: side_formula[0] = "[" + str(side_equ[side1]) + "]" side_formula[1] = "[" + str(side_equ[side2]) + "]" if side3 in side_equ: side_formula[2] = "[" + str(side_equ[side3]) + "]" else: side_formula[2] = str(side3) sum_side_result_lst.append(side_formula) sum_side_result_lst = list(map(list, set(map(tuple, sum_side_result_lst)))) #二次元配列の重複削除、調べたらこんな方法が出てきた for side1, side2, side3 in sorted(sum_side_result_lst, key=lambda x: x[2]): print(side1 + " + " + side2 + " == " + side3) print() print("三角形") for k, tri1 in triangle_lst.items(): angle1_val = tri1[0] + "[" + str(angle_equ[tri1[0]]) + "]" if tri1[0] in angle_equ else str(tri1[0]) side1_val = tri1[1] + "[" + str(side_equ[tri1[1]]) + "]" if tri1[1] in side_equ else str(tri1[1]) angle2_val = tri1[2] + "[" + str(angle_equ[tri1[2]]) + "]" if tri1[2] in angle_equ else str(tri1[2]) side2_val = tri1[3] + "[" + str(side_equ[tri1[3]]) + "]" if tri1[3] in side_equ else str(tri1[3]) angle3_val = tri1[4] + "[" + str(angle_equ[tri1[4]]) + "]" if tri1[4] in angle_equ else str(tri1[4]) side3_val = tri1[5] + "[" + str(side_equ[tri1[5]]) + "]" if tri1[5] in side_equ else str(tri1[5]) print("" + k + " : [" + angle1_val + ", " + side1_val + ", " + angle2_val + ", " + side2_val + ", " + angle3_val + ", " + side3_val + "]")
ジュニア算数オリンピック 二次元上のユークリッド幾何の問題 その11
【随時更新】ユークリッド幾何学の定理や作図まとめ - ニート歴10年からの数学日記 を機械的に適用して、解答に至れるかを探る。分かりやすくするために、段階に分けて名前を付けることにした。その段階という区切りで繰り返したりするんで。
06年度トライアル問題 問題9
『図の四角形ABCDはAB=BC=CDで、角B=168度、角C=108度です。角Dの大きさを求めなさい。
』
セットアップ
三角形を探して、角や辺のイコールを探して、それらを統合する。三角形定理ループに備える。
点に着目して三角形を探す。繋がっている点からも別の繋がっている点に繋がっていたら、三角形。
着目した点。繋がっている点。 見つかった三角形。
A。B、D。
B。C。
C。D。
D。
問題文のイコールを記述する。
イコールの辺。
AB、BC、CD。
対頂角も平行線の同位角や錯角も無し。
side := [
0 : [AB, BC, CD]
]
普段だったら三角形のリストとイコールのリストを統合する所だが、三角形のリストは無し。
三角形定理ループも、角や辺の和も無いんで、もうさっさと作図の段階に入る。
作図
以下4種類の作図をしていく。直接作図したもの以外に三角形や、あるいは正四角形や正五角形ができていたら、次の定理ループで角度が明らかになる可能性がある。
- 点と点を結んで線にする
- 点と点の距離の分だけ線を延長
- 2点と、その間の垂直線とどこか1辺の交点による、二等辺三角形の作図
- 同じ三角形を(同じ長さの辺の所に)作図
- 正四角形
- 正五角形
じゃあ、点と点を結んで線にする所から。
点Aを結ばれていない点Cと結ぶ。まだ基準がハッキリしないけど、新しく三角形を作ったから三角形定理ループにかけてみようか。
新しく作られた三角形を探す。辺ACに着目する。点Aだけに着目すれば良いかと思ったけど、辺ACに含まれる全ての点に着目した方が良い。
着目した点。繋がっている点。 見つけた三角形。
A。B、C、D。 ABC、ACD。
C。B、D。
triangle := [
ABC : [BAC, AB, ABC, BC, ACB, AC],
ACD : [CAD, AC, ACD, CD, ADC, AD]
]
新しく生まれた定義や対頂角や平行線をイコールのリストに登録する。特に無し。
三角形とイコールのリストを統合する。これでセットアップは完了。
triangle := [
ABC : [BAC, AB[0], ABC, BC[0], ACB, AC],
ACD : [CAD, AC, ACD, CD[0], ADC, AD]
]
三角形定理ループにかける。
1つの三角形に2つの同じ角。ある。
三角形。 結果。
ABC。 BAC = ACB。
angle := [
0 : [BAC, ACB]
]
1つの三角形に2つの同じ辺。ある、が既に対応済み。
2つの三角形の2つの角が同じ、更には対応する1辺が同じ。無い。
2つの三角形の2辺とその間の角が同じ。無い。
2つの三角形の3辺が同じ。無い。
角の和と辺の和の段階に入る。
単純な角の和。点に着目して発見する。
着目した点。 角の和。
A。 BAC[0] + CAD = BAD。
C。 ACB[0] + ACD = BCD。
三角形の外角。三角形に着目する。しかし、外角が発生するような三角形は無し。
式の2つが同じだったら残りの1つも同じだが、無し。
辺の和も無し。
っと、ここで気付いたが、168°だとか実際の数字が出てくると、内角が合計180°というのも考えるべきだな。
「角1 + 角2 + 角3 = 180」という式で表すか。
BAC[0] + ABC + ACB[0] = 180
CAD + ACD + ADC = 180
いやしかもABC = 168なのか。
angle := [
0 : [BAC, ACB, 6],
1 : [ABC, 168],
2 : [BCD, 108]
]
こんな感じの表記で良いだろうか。
そうすると、
[0] + CAD = BAD
[0] + ACD = [2]
6 + ACD = 108、ACD = 102
angle := [
0 : [BAC, ACB, 6],
1 : [ABC, 168],
2 : [BCD, 108],
3 : [ACD, 102]
]
CAD + ACD[3] + ADC = 180
まあでもこんなもんか。
triangle := [
ABC : [BAC[0], AB[0], ABC[1], BC[0], ACB[0], AC],
ACD : [CAD, AC, ACD[3], CD[0], ADC, AD]
]
三角形定理ループにかけても特に影響無し。
判明したものが辺ACに関するものばかりだったんで、この作図には意味が無かった。
ちょっと初めてだったんでゴチャゴチャした。休憩(2回目)。
じゃあ次は、点BとDを結ぶ。
着目した点。繋がっている点。 発見した三角形。
B。A、C、D。 ABD、BCD。
D。A、C。
triangle := [
ABD : [BAD, AB, ABD, BD, ADB, AD],
BCD : [CBD, BC, BCD, CD, BDC, BD]
]
新しく追加された定義や対頂角や平行線は無し。
元々のイコールのリストと統合。
triangle := [
ABD : [BAD, AB[0], ABD, BD, ADB, AD],
BCD : [CBD, BC[0], BCD, CD[0], BDC, BD]
]
これでセットアップは完了。
三角形定理ループにかける。
1つの三角形の2角が同じ。無い。
1つの三角形の2辺が同じ。ある。
三角形。 結果。
BCD。 CBD = BDC。
ああ、そうだ、実際の数字とのイコールも登録しておくんだった。
angle := [
0 : [CBD, BDC],
1 : [ABC, 168],
2 : [BCD, 108]
]
最初に戻って、1つの三角形の2角が同じ。あるが対応済み。
1つの三角形の2辺が同じ。あるが対応済み。
2つの三角形の2角が同じ、更には対応する1辺が同じ。無い。
2つの三角形の2辺とその間の角が同じ。無い。
2つの三角形の3辺が同じ。無い。
角の和と辺の和の段階に入る。
単純な角の和。
着目した点。 角の和。
B。 ABD + CBD[0] = ABC[1]。
D。 BDC[0] + ADB = ADC。
三角形の内角や外角。
着目した三角形。 角の和。
ABD。 BAD + ABD + ADB = 180。
ABD。 BAD + ADB = CBD[0]。
BCD。 CBD[0] + BCD[2] + BDC[0] = 180。
BCD。 BCD[2] + BDC[0] = ABD。
統合する。[1] = 168、[2] = 108。
ABD + [0] = 168
[0] + ADB = ADC
BAD + ADB = [0]
108 + [0] = ABD
BAD + ABD + ADB = 180
[0] + 108 + [0] = 180
「[0] + 108 + [0] = 180」より、[0] = 36。
うーん、しかしそうすると、「ABD + 36 = 168」と「108 + 36 = ABD」で矛盾が出るな。
いや、この問題は2ステップの作図が必要で、このままだと膨大な作業量になってしまうので、部分的にでも自動化を模索したい。今回はここで切る。