CakePHP 3 の ビルトインサーバ の実態がなんなのか気になったので 調べました。 php bin/cake.php server
で動くサーバです。
Kenji のすべての投稿
多面体 デカルトの定理を証明する
多面体ではオイラーの定理に並んで、デカルトの定理というのがあります。
多面体についての考察
多面体は、形はどうあれ、ボールのように丸く壁がつながっています。 丸くなっているということは、なにか性質がありそうです。 わかりやすい正多面体について調べてみます。
正多面体について、 各頂点に集まる角度の総和は 360度 よりも少ないはずです。 360度だと平面になってしまいますから。
例
試しに正4面体について計算してみます。
正4面体の面は 正3角形 で 1つの角は 60度 です。 1つの頂点には 3つの面が集まっていますから、 1つの面に集まる角度の総和は
\[ 60 \times 3 = 180 \textrm{度} . \]平面(360度)との差(角不足)は
\[ 360 – 180 = 180 \textrm{度} \]頂点は全部で 4つあるので 全頂点での角不足総和は
\[ 180 \times 4 = 720 \textrm{度} \]です。
同じようにすべての正多面体について角不足総和を求めると下の表のようになります。
1つの頂点に集まる角度の総和 | 平面(360度)との差(角不足) | 全頂点での角不足総和 | |
---|---|---|---|
正4面体 | 180度 | 180度 | 720度 |
正6面体 | 270度 | 90度 | 720度 |
正8面体 | 240度 | 120度 | 720度 |
正12面体 | 324度 | 36度 | 720度 |
正20面体 | 300度 | 60度 | 720度 |
立体全体での角不足は720度になりますね。
実際のところ、多面体の角不足の総和は 720度 になります。 これをデカルトの定理と呼んでいます。
本当かどうか、証明してみましょう。
証明
多面体の頂点、辺、面の数をそれぞれ \( V \) 、 \( E \) 、 \( F \) とします。 オイラーの多面体定理を考えるで書いたとおり、次の式が成り立ちます(オイラーの定理)。
\[ V – E + F = 2 \]多面体での各不足を計算します。 多面体全体での角不足は、 (360度) × ( 頂点の数 ) – ( 各面の内角の総和 ) で計算できます。
\[ (360 \textrm{度} ) \times ( \textrm{頂点の数} ) = 360 V \]は ( V ) の定義より明らかですので、多面体全体での角不足は
\[ 360 V – (\textrm{全ての面の内角の総和}) \]となります。 そこで、 1つの面の内角の総和を計算し、 全ての面について足し合わせます。
ひとつの面の内角の総和
多面体のひとつの面(多角形)について 、 辺の数を \( e \) とします。 この多角形(\( e \) 角形)の内角の総和は
\[ (e – 2) \times 180 \]となります。
これを全ての面の分だけ足します。
全ての面の内角の総和
先ほどの \( e \) を用いて次のように表せます。
\begin{eqnarray} & \sum \left\{ (e – 2) \times 180 \right\} = & 180 ( \sum e – \sum 2 ) \end{eqnarray}\( \sum \) は総和を意味します。
\( \sum e \) は全ての面について辺の数を足したものです。 全ての面について辺の数を足すと、 それぞれの辺を2回数えることになりますから、 \( \sum e = 2 E \) となります。 また、面の数 \( F \) だけ和を計算しますから \( \sum 2 = 2 F \) になります。
よって、 多面体全体での総和は次のように表されます。
\begin{eqnarray} & & 180 ( \sum e – \sum 2 ) \\ & = & 180 ( 2 E – 2 F ) \\ & = & 360 ( E – F ) \end{eqnarray}多面体全体での角不足は
\begin{eqnarray} & & 360 V – \left\{ 360 ( E – F ) \right\} & = & 360 ( V – E + F) \\ & = & 360 \times 2 \\ & = & 720 \end{eqnarray}オイラーの定理は凸多面体でなくても成り立ちますから、 デカルトの定理も同様に成り立ちます。
オイラーの多面体定理を証明する
オイラーの多面体定理を考えてみましょう。 (もともとはグラフ理論での定理なのですが。)
オイラーの多面体定理
多面体では次の等式が成り立つ。
頂点の数 – 辺の数 + 面の数 = 2
平面上の図形においてもこの式は成り立つ。
今回はこの式が本当に正しいのか検証してみようという趣旨です。 オイラーの式は平面上で成り立つ式なので、平面上で考えます。 多面体は平面図形に置き換えられるので、 平面図形でオイラーの式が成り立てば 多面体でも成り立つことになります。
多面体を平面に投影する
多面体は平面図形に投影することができます。
左の4面体は右のように平面に投影できます。 4面体の面は4角形になったのが3つ、残る面はまわりのエリアです。 点と線で 4つの区域に分けられていますね。
証明
平面上に描かれた点と線を考えます。 線の両端が点だと考えてください。 全ての線は点を介してつながっているものとし、点以外では線がつながらないものとします。 線は曲線も含みます。
数学的帰納法で考えます。 点の数を \( V \) 、 線の数を \( E \) 、 面の数を \( F \) とします。 \( V – E + F = 2 \) を証明すればOKです。
\( E = 1 \) のとき
辺 \( E \) は 1, 面 \( F \) は 1, 点 \( V \) は 2 です。
\[ V – E + F = 2 – 1 + 1 = 2 \]オイラーの式は成立しています。
\( E = k \in \mathbb{N} \) でオイラーの式が成り立つとき
\( E = k \) でオイラーの式が成立するときの \( E \) 、 \( V \) 、 \( F \) の値をそれぞれ \( E_k \) 、 \( V_k \) 、 \( F_k \) とすると、次の式が成り立ちます。
\[ V_k – E_k + F_k = 2 \]ここで \( V_k \) 、 \( F_k \) の値は \( k \) によって一意に定まるものではなく、 あくまで前提とした条件での値です。
図形に線を足す場合を考えます。 線は点を介してつながっているので、新しく引く線は両端または一方の端が既存の線とつながります。
線の一方のみが既存の点に接続する場合
点が新たに1つ増えるので \( V = V_k + 1 \) 、 線が新たに1つ増えるので \( E = E_k + 1 \) 、 面の数は変わらないので \( F = F_k \) 。
\begin{array}{cl} & V – E + F \\ = & ( V_k + 1 ) – ( E_k + 1 ) + F_k \\ = & V_k – E_k + F_k \\ = & 2 \end{array}線の両端が既存の点に接続する場合
新しく線を引く前の状態で、 既存の線は繋がっているため 新しく引く線の片側または両側は線が閉じていることになる。 すなわち線を新しく引くと、 面の数が1増える。
これより 点の数は増えず \( V = V_k \) 、 線の数は1増えて \( E = E_k + 1 \) 、 面の数も1増えて \( F = F_k + 1 \) 。 これは 線の始点と終点が同じ場合も含みます。
\begin{array}{cl} & V – E + F \\ = & V_k – ( E_k + 1 ) + ( F_k + 1 ) \\ = & V_k – E_k + F_k \\ = & 2 \end{array}以上より、 \( E = k \in \mathbb{N}\) で オイラーの式が成立していれば \( E = k + 1 \) でも成立することが分かる。
よって すべての場合で オイラーの式は成立する。
証明にしてはちょっとゆるい感じがしますが、 式が成り立つことを理解していただけるとうれしいです。
このオイラーの定理を使うと、デカルトの定理も証明できます。 詳細は デカルトの定理を証明する をご覧ください。
haskell split カンマ区切りの文字列をカンマで区切って配列にする方法
haskell で ruby の split や PHP の explode にあたるようなものを考えました。
背景
haskell を使ったことがなく、使う場面もなかなかないので CodeIQ で使ってみようと思ったものの、 「入力を受け取るにはどうすればいいんだ?」という疑問にぶちあたり、 split する方法を考えました。
Haskell には Data.List.Split
モジュール内 に splitOn
という関数があるのですが、 CodeIQ でコンパイルに失敗しました。 Ideone でも コンパイルに失敗しました。 ほかにも関数はあるそうなのですが、うまくいかなかったので自分で考えることにしました。
カンマで分割する方法
下のようになりました。 この方法だと カンマ でのみ区切ります。
1 2 3 4 5 6 7 8 9 10 |
split = _split [] _split ts "" = ts _split ts s = _split (ts ++ [(token s)]) (drop (length(token s) + 1) s) token = _token "" _token ys "" = ys _token ys (x:xs) = do if x == ',' then ys else _token (ys ++ [x]) xs |
任意のデリミタで分割する方法
任意のデリミタを指定できるようにしてみました。 1文字のデリミタでのみ分割可能です。
1 2 3 4 5 6 7 |
split d = _split d [] _split d cs "" = cs _split d cs s = _split d (cs ++ [token d s]) (drop (length(token d s) + 1) s) token d = _token d "" _token d t "" = t _token d t (x:xs) = if (x == d) then t else _token d (t ++ [x]) xs |