隠し部屋の秘境

豆知識的な小ネタ見つけては投稿していきます

Denoでsupabaseを使うまでの一連の流れ

この記事では、Denoからsupabaseにアクセスする方法を解説していきます。
まだ習いたての初心者でにわかですが、
にわかだからこそ初心者向けにはわかりやすい説明ができるのでは?と思っています。
単純に説明が下手、とかがなければね。

この記事の対象

  • とりあえず動いて、データベースが使えればいいと言う人
  • jsでサーバースクリプト作ってる人

分かり易さ優先で厳密な事には一切触れません。
安全性もあったもんじゃありません。

また、前提としてある程度は自分で調べて見たものとして、
少なくとも次の事が押さえてあるとします。

  • Denoのserveが使える
  • supabaseのアカウントがありプロジェクトがありパスワードを覚えている

この上で、Denoでsupabaseが使えるために追加で必要な事が次のたった2つです!

タスク

  1. SQLiteの構文を理解する
  2. それをjsに組み込む方法を理解する

既に分かるものは無視しておk
それでは順番に行こう

1. SQLiteの構文

項目1としましたが正直、後回しでもいいです。
まずはじめに言います。
インストール関連の必要は全くありません。
SQLiteはあくまでデータベースのための文法(→単なる知識教養)という認識でいいと思います。
MySQLというのもあるようですが、SQLiteとは別物っぽいです。

なので、実際にDenoではSQLiteのソフトは不要なので、そっちは勉強用に使うくらいでいいかと。

データベースを扱う際に大抵欲しいのが取得,追加,更新,削除。この辺りだと思います。
ここでも軽く触れはしますが、それよりもおすすめの記事がございます。m(*_ _)m

ここで触れるのは最低限だけの事です。

2. jsに組み込む方法

まずはサーバースクリプトを開きます。
importは次のものを追加します▶︎
import * as postgres from "https://deno.land/x/postgres@v0.14.0/mod.ts"

次にスクリプトの最初らへんに次のものを追加します▶︎
const pool = new postgres.Pool(接続文字列)
ここで「接続文字列」は次の場所にあります。

ここまでの内容はserveの外側に記述するものですが、これ以降は内側に記述します。

  • データベースの接続と解放

supabaseを使う始めの位置に記述します▶︎

const connection = await pool.connect();
一方、使い終わりの位置に記述します▶︎
connection.release();

  • データベースの操作

SQLite構文を次のように埋め込んで記述します▶︎

const response = await connection.Query`
SQL構文
`;
例えば、testというテーブルのうち、idというカラムが'foo'という値の行の、barというカラムに変数buzという値をセットする場合は次のようにします。
const response = await connection.Query`
UPDATE test SET buz=${buz} WHERE id=${'foo'}
`;
あとは始めと終わりの間は自由にデータベース操作ができます。

ここで注意事項はあります。

  • テーブル名及びカラム名には大文字とハイフン(-)が使えません。アンダーバー(_)は使えることを確認。

大文字はsupabase側で勝手に小文字に変換され、ハイフンはエラーになります。

  • 値以外の構文の部分を関数や変数で普通に作ろうとするとエラーになります。逆に値は直接埋め込んでも可です。

その理由はこちらを参考に分かります。
テンプレートリテラル (テンプレート文字列) - JavaScript | MDN

またGETリクエストの場合、返ってくる値はJSON形式となっており、テーブルのデータはrowsに格納されています。要するに、
response.rows
でお目当てのデータを取得できるかと思います。

まとめ

この記事の全体の構造

  1. 前提
  2. SQLiteの構文
  3. jsに組み込む方法
    • serve関数外でsupabaseの準備
    • serve関数内でsupabaseの操作

積和の公式は覚えよう

高校2年生位で習う積和の公式ですね。
割と面倒くさくて覚えたくない人も多いはず?(分からん)
先生によっても覚えろ派と覚えるな派がいると思いますが、大半は覚えるなと言うんじゃないでしょうか(正直これも分からん)
しかし自分は、積和の公式は覚えるべきだと思うんですよね。
今回はその旨について述べて行こうと思います。
(賛否両論なので持論だけ投げて終わりにしようと思います。未だ確信は持てないので)

理由1

積分で加法定理を使うことはないが積和の公式ならよく使う
まず次の積分を見てください。
\int \sin{(x+a)}dx
この被積分関数は加法定理によって展開すると思いきや、全く必要ありません。
t=x+aとおきます。dt=dx。
すると
\int \sin{(t)}dt
となるので積分できますね
-\cos{(t)}+C\\\ =-\cos{(x+a)}+C

次に、次の積分を見てください。
\int \sin{(3x)}\cos{(2x)}dx
ここで、\sin{(3x)}=\sin{(2x+x)}=\sin{(2x)}\cos{(x)}+\cos{(2x)}\sin{(x)}と展開すると、
 \sin{(2x)}\cos{(2x)}\cos{(x)}+\cos{(2x)}\cos{(2x)}\sin{(x)}\\\ =\dfrac{\sin{(4x)}\cos{(x)}}{2}+\dfrac{(1+\cos{(4x)})\sin{(x)}}{2}\\\ =\dfrac{\sin{(x)}}{2}+\dfrac{\{\sin{(4x)}\cos{(x)}+\cos{(4x)}\sin{(x)}\}}{2}\\\ =\dfrac{\sin{(x)}}{2}+\dfrac{\sin{(5x)}}{2}
このように随分手数が必要ですが、積和の公式を使えればこの結果が直接得られるわけです。
\sin{(3x)}\cos{(2x)}=\dfrac{1}{2}{\sin{(3x-2x)}+\sin{(3x+2x)}}\\\ =\dfrac{1}{2}{\sin{(x)}+\sin{(5x)}}
最終的に積分
-\dfrac{1}{2}\cos{(x)}-\dfrac{1}{5}\cos{(5x)}
となります。

理由2

積和の公式は"中央"に位置する
積和の公式を覚えるべきである最もたる理由がこっちです。
みなさんはホームポジションという考え方をご存知でしょうか。
バドミントンやテニスやってる人なんかだとよく知っていると思います。
要は、コートの中央に陣取って飛んできた球に合わせて少し手を伸ばすと打ち返せるという、応答性に優れた手段ですが、
積和の公式もこれと似たようなことが言えるのです。
積和の公式はちょっと変形するだけで2倍角の公式にも半角の公式にも和積の公式にも加法定理にもなります。
まさに中心に位置するのです。
一方加法定理では、和積の公式まで導くのに一度積和の公式を経由する必要がありますし、2倍角の公式を導くには数回の式変形が必要です。
つまり、これを覚えているか否かで受験などで起動力大きく関わって来るわけです。

理由3

案外覚えやすい。
積和の公式は次の3つしかありません
\cos{A}\cos{B}=\dfrac{1}{2}\{\cos{(B-A)}+\cos{(B+A)}\}
\cos{A}\sin{B}=\dfrac{1}{2}\{\sin{(B-A)}+\sin{(B+A)}\}
\sin{A}\sin{B}=\dfrac{1}{2}\{\cos{(B-A)}-\cos{(B+A)}\}
からしても統一性がありますが、さらに補助的に説明があります。

  • 積がcos同士,sin同士ならcosの和,

cosとsinの積ならsinの和となる

  • 引数は全てB-AとB+A
  • sinとsinの積だけ引き算、それ以外は足し算

→積にcosが混じってたら足し算

  • 1/2{ }は飾り

これは学校で習うのとは、だいぶ違ったと思いますが思いのほか簡単な形してると思いませんか?

理由4

積和の公式は覚える必要がないと主張する人々は実は積和の公式を覚えている。
彼らは加法定理から簡単に導出できるため、覚えなくてよいと主張しがちですが、
sin(a+b)=sin(a)cos(b)+cos(a)sin(b)
sin(a-b)=sin(a)cos(b)-cos(a)sin(b)

両辺を足して
sin(a+b)+sin(a-b)=2sin(a)cos(b)
sin(a)cos(b)=1/2{sin(a+b)+sin(a-b)}
果たして本当に簡単でしょうか?
なんの前提もなしに暗算で処理するには少々計算量があるように思われます。

これを暗算で処理するとすれば、上の2行即ち加法定理の格好が図形的に浮かび上がるレベルで定着していれば直接的に2sin(a)cos(b)がsin(a+b)+sin(a-b)になると算出できそうです。

ですがsin(a+b)とsin(a-b)が登場することは少なくとも覚えています。
なんなら、そこから足し引きするプロセスも覚えており、
それを図形的に処理することも覚えていれば
それはもはや積和の公式を覚えています。
なぜなら、その覚えた導出過程に積和の公式の完成系まで含まれてしまっているから。
要はこんな感じの図形で最早暗記しています。

彼らは"簡単に導出"しているつもりが覚えた事を書き出す作業をしていただけに過ぎないのです。
もちろんその方が確実に記憶出来ますが、加法定理を導出する人がいないように、しかし記憶違いが起こったりはしないように、
積和の公式も使っているうちに間違いなく引き出せるようになるはずです。(未検証)

まとめ

積和の公式を覚えましょう!!

絶対値関数の微分積分

絶対値記号が含まれる式は扱いづらいということで、特に微分積分を行う際なんかは場合分けされがち

しかし、調べてみると直接処理することもできるようなのでまとめました。

結論から言います。

目次

  1. 絶対値の微分 |x|'=x/|x|=|x|/x
  2. 絶対値の2階微分 |x|''=0
  3. 関数の絶対値のn階微分 |f(x)|⁽ⁿ⁾={|f(x)|/f(x)}f⁽ⁿ⁾(x)
  4. 絶対値の積分 ∫|x|dx=1/2{x|x|}

ちなみにxが実数である事を想定しています。

複素数の場合については未検討です。

それでは解説を始めます

1. 微分

\dfrac{d}{dx}|x|=\dfrac{x}{|x|}=\dfrac{|x|}{x}

符号関数とも呼ばれるこれになります。考えてみれば当たり前ですね。証明いきましょう。

証明1

まず次の図を見てください。横軸をx, 縦軸をyとします。

f:id:theEasyPuzzle666:20220803101709p:image

青い実線y=|x|を表しており、その微分係数はそれぞれの領域において赤字で示された通りになります。

ここで|x|×|x|'を考えると、x<0の領域のみ-1倍されて折り返されるためy=xになるというのが黄色い字の式です。

これらを数式で表現します。

0<xの場合

|x|=x, |x|'=1 より

|x|×|x|' = x×1 = x

x<0の場合

|x|=-|x|, |x|=-1 より

|x|×|x|' = (-x)×(-1) = x

x=0の場合

|x| = 0 より

|x|×|x|' = 0×|x|' = 0 = x

以上より

|x|×|x|' = x [完]

同様にx×|x|'=|x|も示せます。

証明2

積の微分を利用する事もできます。

 \color{red}{{f(x)g(x)}'=f'(x)g(x)+f(x)g(x)}

今回、f(x)=g(x)=|x|とします。

すると{|x||x|}' = |x|'×|x| + |x|×|x|' = 2{|x|×|x|'}

一方、{|x||x|}' = (x²)' = 2x

以上より 2{|x|×|x|'} = 2x

∴ |x|×|x|' = x [完]

両辺に|x|/xをかけるとx×|x|'=|x|も得られます。

証明3

定義にしたがった微分と予想の式を比較してみます

0<xの場合

\lim_{h\to 0}\dfrac{|x+h|-|x|}{h}=\lim_{h\to 0}\dfrac{x+h-x}{h}\\\ =lim_{h\to 0}\dfrac{h}{h}\\\ =lim_{h\to 0}1=1

一方、予想の式は

\dfrac{x}{|x|}=\dfrac{x}{x}=1

x<0の場合

\lim_{h\to 0}\dfrac{|x+h|-|x|}{h}=\lim_{h\to 0}\dfrac{-(x+h)-(-x)}{h}\\\ =lim_{h\to 0}\dfrac{-h}{h}\\\ =lim_{h\to 0}-1=-1

一方、予想の式は

\dfrac{x}{|x|}=\dfrac{-x}{x}=-1

x=0の場合

右から極限

\lim_{h\to +0}\dfrac{|x+h|-|x|}{h}=\lim_{h\to +0}\frac{x+h-x}{h}\\\ =lim_{h\to +0}\dfrac{h}{h}\\\ =lim_{h\to +0}1=1

左から極限

\lim_{h\to -0}\dfrac{|x+h|-|x|}{h}=\lim_{h\to -0}\dfrac{-(x+h)-(-x)}{h}\\\ =lim_{h\to -0}\dfrac{-h}{h}\\\ =lim_{h\to -0}-1=-1

よって極限は存在しない。

一方、予想の式は

\dfrac{x}{|x|}=\dfrac{0}{0}

よって定義できない。

以上より全ての実数xについて

\dfrac{d}{dx}|x|=\dfrac{|x|}{x}

が成立する。[完]

x×|x|'=|x|も同様に示せます。

 

以上、3通りの証明を行いました。

厳密性はともかく、結果が最もらしいことは分かっていただけたかと思います。

2. 2階微分

 \dfrac{d^{2}}{dx^{2}}|x|=0\,(x\ne0)

2回微分は0です。x=0では微分は定義できません。

証明

1階微分は上で求めました。

\dfrac{d}{dx}|x|=\dfrac{x}{|x|}=\dfrac{|x|}{x}

2回微分は次のようになります。

\dfrac{d^{2}}{dx^{2}}|x|=\dfrac{d}{dx}\{\dfrac{|x|}{x}\}

ここで、商の微分を用います。

\dfrac{d}{dx}\{\dfrac{|x|}{x}\}=\dfrac{|x|'x-|x|x'}{x^{2}}\\\ =\dfrac{\dfrac{|x|}{x}x-|x|}{x^{2}}\\\ =\dfrac{|x|-|x|}{x^{2}}\\\ =\dfrac{0}{x^{2}}

x≠0のとき、これは0になります。

x=0のとき、0/0不定となります。

以上より、

 \dfrac{d^{2}}{dx^{2}}|x|=0\,(x\ne0)

[完]

まあ、結局は一次関数ですからね、2回微分すればそれは0になりますよ

3. n階微分

 |f(x)|^{(n)}=\dfrac{|f(x)|}{f(x)}f^{(n)}(x)

これも答えを見れば当たり前というか特になんの面白みもない。

証明行きましょうね

導出過程

まずは合成関数の微分をします

|f(x)|'=\dfrac{|f(x)|}{f(x)}f'(x)

これをさらに微分しますと、

|f(x)|''=\{\dfrac{|f(x)|}{f(x)}f'(x)\}'\\\ =\{\dfrac{|f(x)|}{f(x)}\}'f'(x)+\{\dfrac{|f(x)|}{f(x)}\}f''(x)

積の微分をつかいました。

ここで、\{\dfrac{|f(x)|}{f(x)}\}'の部分ですが、

 \dfrac{d^{2}}{dx^{2}}|x|=0\,(x\ne0)のxにf(x)を代入したものとなっています。よってf(x)≠0で0となるので、

\{\dfrac{|f(x)|}{f(x)}\}'f'(x)+\{\dfrac{|f(x)|}{f(x)}\}f''(x)=0+\{\dfrac{|f(x)|}{f(x)}\}f''(x)\,(f(x)\ne0)

となります。

一方f(x)=0のとき、絶対値の微分は定義できないのですが、

\{\dfrac{|f(x)|}{f(x)}\}'

の部分も0/0不定となるので、左辺と右辺がどちらも未定義という事でf(x)=0の場合も成り立つと言えます。

以上より

|f(x)|''=\{\dfrac{|f(x)|}{f(x)}\}f''(x)

となります。

これを繰り返すと次の規則に気づきます。

 |f(x)|^{(n)}=\dfrac{|f(x)|}{f(x)}f^{(n)}(x)

証明

まあ数学的帰納法ですよねー,

n=1の場合は導出過程で示しました。

なんならn=2の場合も示しました。

ここで、ある整数kについて

 |f(x)|^{(k)}=\dfrac{|f(x)|}{f(x)}f^{(k)}(x)

が成り立つと仮定します。

すると

 |f(x)|^{(k+1)}=\{|f(x)|^{(k)}\}'\\\ =\{\dfrac{|f(x)|}{f(x)}f^{(k)}(x)\}'\\\ =\{\dfrac{|f(x)|}{f(x)}\}'f^{(k)}(x)+\{\dfrac{|f(x)|}{f(x)}\}f^{(k+1)}(x)\\\ =\dfrac{|f(x)|}{f(x)}f^{(k+1)}(x)

よりk+1の場合でも成り立つことが分かります。

以上より全ての自然数nについて

 |f(x)|^{(n)}=\dfrac{|f(x)|}{f(x)}f^{(n)}(x)

が成り立ちます。[完]

若干誤魔化しが入っている気がするかもしれませんが、使用上は本当に問題ないです。

4. 積分

\int |x|dx=\dfrac{1}{2}x|x|+C

積分も一応定義できる。しかし積分は結構危険なのでこの程度にしておきます。

なんだかんだで結果は当たり前ですね。分かってくれたと思いますがCは積分定数です。

証明

\dfrac{d}{dx}|x|=\dfrac{|x|}{x}

を次のように変形します。

x\dfrac{d}{dx}|x|=|x|

\int |x|dx=\int x\dfrac{d}{dx}|x|dx+C

部分積分を使います。

\int x\dfrac{d}{dx}|x|dx=x|x|-\int |x|dx+C

2\int x\dfrac{d}{dx}|x|dx=x|x|+C

\int |x|dx=\dfrac{1}{2}x|x|+C

[完]

あっさり証明完了

まとめ

いかがでしたか?

自分は場合分けのいらない絶対値の微分積分は新鮮で素敵だと感じます。

例えば|cosx|'は

sinx (2nπ<x<2nπ+π/2, 2nπ+3π/2<x<2nπ+2π), -sinx (2nπ+π/2<x<2nπ+3π/2)

ではなく、|cosx|tanxと表せるのです。

解くのが楽というのもありますが、解が綺麗なんですね。

ただ、これをテストなどで使っていいかと言われると、全くおすすめできません。ですが先生に尋ねる価値はあるのではないかと思われます。

 

最後に、ここまで読んで頂きありがとうございました!

余り演算の性質

目次へ余り演算とは次のようなもの
a%b=aをbで割った余り
数学ではこの演算子よりも合同式を使われがちですが、コンピューター分野ではバリバリこっちです。
ただ、この%演算は処理しづらく、一度に複数組み込むと式が汚くなってしまいます。(処理すると可読性は下がります。注釈しましょう)
しかし、調べてみると便利な性質を持つようなのでまとめました。

結論から言うと次のような性質があります。
(名前は勝手につけました。ご指摘があればコメントよりお願い致しますm(_ _)m)

目次

  1. 基本則 a=[a/b]×b+a%b
  2. 周期性 (a+kb)%b=a%b
  3. 和の冪等性 (a+b)%c={(a%c)+b}%c
  4. 積の冪等性 (a×b)%c={(a%c)×b}%c
  5. 指数の冪等性 (a^b)%c={(a%c)^b}%c
  6. 分配法則 c(a%b)=ac%bc
  7. 商の余り [a/b]%c=(a%bc-a%b)/b
  8. 省略定理 (a%b)%c=a%b (b≦c)
  9. 短絡定理 (a%b)%c=a%c (bはcの倍数)
  10. 減法定理 (a-b)%a=(a-1)-(b-1)%a (1≦b

番外

今回は証明構造がユニークなので良い頭の体操になります。良ければ皆さんも考えてみてくださいね!

それでは解説を始めます

a=[a/b]×b+a%b

まずは基礎です。前提の伝え合わせも兼ねておきます。
[x] : xを超えない最大の整数
→ここでは0≦xを想定して「切り捨て」の演算子として用いています

その上で、この式は
商×割る数 + 余り = 割られる数
を意味している事がわかると思います。
要は小学校の算数ですね。

当たり前っぽいですが一応基本方針の提示として証明しておきます。

これは普通に青チャートとかにも載ってるので安心して使って大丈夫です。

(a+kb)%b=a%b

kbはbの倍数を意味しています。
要するに割る数の倍数を足しても余りは変わらないことを表現しています。

詐欺的に%演算が出てきたと感じるかもしれません。
日本語に訳せば解決します。
aをbで割った余り、a+bcをbで割った余り、どちらもRになったということです。ここの対応が定着すれば大した事じゃないです。
ポイント
kbをQとまとめる発想と、それをまとめて商と見なせるかが鍵になってきます。代数学的なセンスが問われる所だと思います。

(a+b)%c={(a%c)+b}%c

先に和の要素の余りを計算しても最終的な余りは変わらないことを表現しています。

①~③はだいたい同じような事を言っています。
ポイント
とりあえず律儀に、(a+b)÷c, a÷c, b÷c それぞれの商と余りを定義したところから始めたとしても、
a=cQa+Raなどをa+bに揃えた時点でおのずと答えが出たことと思います。
恐らくこれは殆どの人が解けたのではないでしょうか。

(a×b)%c={(a%c)×b}%c

先に積の要素の余りを計算しても最終的な余りは変わらないことを表現しています。

これも殆どの人は出来たんじゃないだろうか?
ポイント
掛け算が足し算のかき集めである事を連想出来ればが使えそうだと気づけます。

(a^b)%c={(a%c)^b}%c

数学の合同式でよく知られるやつです。合同式では、aの代わりは同位相であればなんでも良かったので若干意味が異なります。
しかしまあ、をぶち込んでやればそちらも再現可能です

ポイント
の証明と全く同じ形ですね

k(a%b)=ka%kb

まさかの分配法則持ち演算子です。交換法則も結合法則もありません。分配法則だけです。

証明見たら普通に当たり前なんですが、コイツが中々便利なんですわ
ポイント
実は出来心でa = bQ+Rの両辺にkをかけてたまたま発見しました。証明しようと思ってすると案外難しいのかもしれない。

[[a/b]/c]=[a/bc]

a,b,cは任意の自然数です。切り捨てを纏められる事を言っています。
%演算が不在ですが証明では便利なので挙げました。番号が⓪なのはもはや%演算の性質じゃないからです。

なっげぇぇぇぇぇぇ。。。短くならないんか!
ポイント
これ以外に思いついきませんでした。まじでエグいです。もっとスマートな証明考え中です。

[a/b]%c=(a%bc-a%b)/b

正直どう役に立つのか検討もつかないですが、証明するだけしてみましょうか。

さしずめこれもなんかの証明に使うんでしょうね。
ポイント
[a/b]%cの%演算を何とかしたかったので、無から%演算を生成するを逆に辿ることで処理出来るのではないかと考えました。

(a%b)%c=a%b (b≦c)

ある数で余りを計算した後、それ以上の数で割っても余りは変わらないことを言っています。
意味的には当たり前ですね。証明してみましょう。

まさかの証明出来ました。
もそうでしたけど、当たり前な事を証明するのって難しいんですね。
ポイント
Rbをそれより大きなcで割る時点で商が出ない,すなわちQc=0となるのは予想できたので、それを証明するためにQc=0以外の場合では何かしら不都合が生じるはずだと予想できました。背理法まっしぐらです。

(a%b)%c=a%c (bはcの倍数)

倍数なら上書き出来るという事です。(説明雑)

証明では触れませんでしたが、
aをbで割った商をQb, cで割った商をQcとすればQb = Qc%k となって奥が深いです。
ポイント
b=kcと表現するのはいいとして、商を定義して生真面目に商の形を求めようとするとを含めとんでもない記述量になったので割愛しました。を使うことで商を考えずに済んだのが大きいです。完璧主義だとこれに気づけないかも知れません。

(c-b)%c=(c-1)-(b-1)%c (1≦b<c)

割られる数に割る数が含まれている場合も、この条件下では分離する事ができます。

ポイント
意識した点は2つです。
1つ目は、%演算の中にマイナスを残したくなかったので、マイナスが着いているbを主人公にした事です。
2つ目は、最初はb=cQ+Rで定義していたのですが余りの範囲が0≦c-R<c-1となったため、その調整としてb-1=cQ+Rで定義し直したところから書き始めています。調整の対象がbなのはcでは上手くいかないからです。

// QUEST_/

現在苦戦している未解決問題がこちら

1. a%(b+c)のbとcを分離せよ!

2. (a%b)%cを一般化せよ!

3. [[a/b]/c]=[a/bc]を簡潔に示せ!

4. 実数へ拡張せよ!

以上4つになります。解決できる保証はありませんが楽しみにしててください

unicodeのひらがなと50音表を対応させる

どうも。今回はひらがなをひらがならしく扱いたいという事で関数を作成しました。

ひらがなをひらがならしく?と思いましたよね

まあすぐに意味が分かると思います。

目次

はじめに

Unicodeのひらがなは次のような順番で並んでいます。

ぁあ…かが…さざ…ただ…つづてで...なにぬ…はばひび…ま…ゃや…ら…ゎわゐゑをん

ある程度は規則的に並んでいるものの、簡単な法則で表そうとすると案外上手くいかない。

そこで、これを次のような50音表のように扱える関数を考えることにしました。

f:id:theEasyPuzzle666:20220722080800j:image

これを見る限り、ひらがなは次の3つの要素に分解出来ることが分かります

かな文字 = (行,段,種)

行: 横軸, 子音を決める

段: 縦軸, 母音を決める

種: 濁点や小文字などのオプション

 

例えば、「ぢ」ならた行,イ段, 濁点ありで(3,1,1)となります。

この2番目の数字から「ぢ」がイ段である事を取得できたり、3番目の引数を0にすれば濁点を落とせたりと、ひらがなとして扱いやすい表現である事が分かります。

これを「かな文字表現」と呼ぶことにします。

 

つまり逆に言えば、ひらがなをこの3つの要素に分解する事で扱いやすい50音表を構築しようという訳です。

では肝心の分解する方法はどうしたら良いでしょうか?

まずは分かりやすさのために要点をまとめて説明します。結果だけ知りたい場合はこちら

基礎概念や導出過程などは後ほど。

構築手順

Step1: かな文字表現→Unicode

まずはかな文字表現からUnicode値を求める関数から考えていきます。その後で逆変換を求めます。

以降、Unicode値をUまたはU値と呼びます。

Unicodeにおける最初のひらがなは「ぁ」で値は12353です。この値が基準値となります。土台です。

ここでかな文字表現の5×行+段に相当する値をXで置くことにします。この値が骨組みのような役割を担います。

後は肉付けとして補正項を導入します。濁点付きの文字などが一切なければXで十分ですが、残念ながらあるので、文字によって値にズレが生じてきます。そのズレを個々にεとします。

するとそれをかき集めてやれば、ズレを修正することができる訳です。

ここまでで、U = 12353 + X + ∑ε と表せることが分かります。

問題は補正項の求め方です。

これは効果の範囲と値を指定してやる事で解決します

その方法ですが、

ε = (X-開始)×オプションの種数 (開始≦X<終了) & ズレの合計 (終了≦X) とします。

 

例えば、は行に関する補正値は

・開始は「は」(X=25)

・終了は「ま」(X=30)の直前

・オプションの種数は2種類(濁点,半濁点)

・ズレの合計は10個 なので、

ε = 2(X-25) (25≦X<30), 10 (30≦X) となります。

 

また、や行ではイ段,エ段が飛んでいます。ここの表現は次のようにします。

ε = -1×飛ばす個数×増え方 (跳躍先≦X)

 

ここではや行のイ段で説明します。

・跳躍先は「ゆ」(X=37)

・飛ばす個数は1個

・増え方は2づつ なので、

ε = -2 (37≦X) となります。

 

これを他についてもまとめていくと、最終的に式は次のようになります。

U = 12353 + X +

{X (0≦X<20), 20 (20≦X)} +

{X-17 (17≦X<18), 1 (18≦X)} +

{2(X-25) (25≦X<30), 10 (30≦X)} +

{X (35≦X<40), 5 (40≦X)} +

{-2 (37≦X)} + {-2 (39≦X)} +

{X-45 (45≦X<46), 1 (46≦X)} +

{-1 (48≦X)}

 

以下にjavascriptのコードを示します。

※ ≦ は実際は<= です


const KanaToUnicode = function(Row, Stg, Opt){

  const X = 5*Row + Stg;

  return 12353 + X +

    X *(0≦X<20) + 20 *(20≦X) +

    (X-17) *(17≦X<18) + 1 *(18≦X) +

    2(X-25) *(25≦X<30) + 10 *(30≦X) +

    X-35 *(35≦X<40) + 5 *(40≦X) +

    (-2) *(37≦X) + (-2) *(39≦X) +

    (X-45) *(45≦X<46) + 1 *(46≦X) +

    (-1) *(48≦X);

}


 

ちなみにもう少し短く出来ます。

X-17 (17≦X<18)とか0に決まってるので、そういった無駄なのを省略したり、行の範囲は直接行で表現したり、三項演算子というのを使ったりすると


const KanaToUnicode = function(Row, Stg, Opt){

  const X = 5*Row + Stg;

  return 12353 + X +

    (Row<4 ? : 20) + (18≦X) +

    (Row==5 ? 2*Stg : 10 *(5<Row)) +

    (40≦X) + (46≦X) - (48≦X);

}


こんなにすっきりします。

どちらも実行すると上手くいくのが分かります。

Step2: 変数変換

ではこの関数の逆変換を求めていきます。

ここで、12353が邪魔なので、

新たに「規格化Unicode値」NU = U-12353を定義します。

するとNU = X + ∑ε で表せる訳ですね。

補正項のうち、範囲の表現にXが残っているのは厄介なのでNUで表し直します。

その方法ですが、この式のXに開始値, 終了値を代入する事でこれが直接NUの範囲になります。

 

例えば、あ行〜た行の0≦X<20は

  • X=0   で NU=0
  • X=20 で NU=41 より

0≦NU<41といった具合です。

順々に求めていって丸ごと置き換えるだけです。

Step3: 式変形

最後は変数分離を行うのみです。

ただし、場合分け関数なのでこのまま変形するのは非常に非効率的です。

まずは式を1つに絞ります。

つまり、この式のまま実装し、先にNUを代入する事で場合分けを解除します。

後はXが残るので方程式を解かせるプログラムを組めば完了です。数学じゃないので1発公式にする必要は無い訳です。

ここで、Xの係数kと定数cをカウントする関数に路線チェンジします。

するとNU = kX + c ∴ X = (NU - c)/k で表すことが出来ます。

kで割り切れない事がありますが、これはオプションが原因です。NU-cをkで割った余りがちょうどオプションの番号に相当します。

よってオプションもXも求まったため、Unicode値を3つのパラメーターに分解できたという事です。

♢完成です!♢

以下にjavascriptのコードを示します。


const KanaFromUnicode = function(U){

  const NU = U - 12353;

  var k = 1;

  var c = 0;

  //あ行〜た行

  if(0≦NU<41)

    k+=1;

  if(41≦NU)

    c+=20;

  //っ

  if(34≦NU<37){

    k+=1;

    c-=17;

  }

  if(37≦NU)

    c+=1;

  //は行

  if(46≦NU<61){

    k+=2;

    c-=50;

  }

  if(61≦NU)

    c+=10;

  //や行

  if(66≦NU<72){

    k+=1;

    c-=35;

  }

  if(72≦NU)

    c+=5;

  if(68≦NU)

    c-=2;

  if(70≦NU)

    c-=2;

  //わ行

  if(77≦NU<79)

    c+=1;

  if(79≦NU){

    k+=1;

    c-=45;

  }

  //集計

  const kX = NU-c;

  const Opt = kX%k;

  const X = (kX-Opt)/k;

  const Stg = X%5;

  const Row = (X-Stg)/5;

  return {Row, Stg, Opt};

}


長いです。短くする方法検討中です。

 

使用例としては、

KanaFromUnicode関数でRow,Stg,Optを取得して、

  • KanaToUnicode(Row,Stg,0)を行えば濁点が落とせます
  • KanaToUnicode(Row,2,Opt)を行えば同じ行のイ段が取得できます

凄い便利です。

 

ここから下は、自分でも何か編み出したい方が参考にして頂ければ幸いです。

天才だから思いついたでは片付けません。

読めば分かりますが天才的な事は一切ありません。至って自然な成り行きです。

章末にまとめがあります。

発見及び導出の過程

苦労や感動,素晴らしさや魅力を伝えようとすると無駄に長くなるものです。

余談終わり。

KanaFromUnicode関数→KFU関数

KanaToUnicode関数→KTU関数

まず逆変換という発想についてですが、いきなりKFU関数を考えようとすると手も足も出ませんでした。

そのため、参考程度にその逆演算であるKTU関数を考える事にしました。

それでもKFU関数には歯が立たなかったので直接KTU関数を改造できないか考えたという経緯です。

Step1

歯が立たなかったのには理由があります。

かな→Unicodeは3つの引数から1つの値を導くのに対し、かな←Unicodeについては1つの引数から3つの値を導く必要があるのです。

普通に考えたら圧倒的情報不足です。

ここで、Xという定義が登場します。

Xは

KTU関数作成時に「ひらがなをひらがならしく」の名目上、オプションを一切無視した考え方が欲しく、5*行+段を導入したところ頻出したので(書くのが面倒になって)定義した訳ですが、これも1価の数値なのです。

にも関わらず、5で割った商と余りがそれぞれ行と段になる事に気づき、パラメーター数を増やす事は可能な事を確信しました。

その理由が、0≦段<5という条件にある事も分かります。

少なくとも、行と段はXから求めれば良さそうなので、Xとオプションを求める問題に帰着しました。

Step2

とりあえずXを求めてしまいたかったのでオプションは後で考えます。

KTU関数が完成した時点では補正項の範囲はXで表されていました。Xが不明な状態で、補正値がXの範囲で表されると 補正値の選び方も不明になるので、これをUnicodeの範囲に直す必要がありました。

ただ、直そうにもXについて解く前なので(開始≦X<終了)に直接代入,変形する事は出来なそうです。

どうしたら良いでしょうか?

最も頭を抱えた問題ですが、意外にも簡単な方法で解決出来ました。

とりあえずここで邪魔な12353を排除してすっきり考えたかったのでNUが登場しました。

そして、既に解説済みですがXが分かっていればUnicodeを求める事はできる状態なので、Xの開始,終了の値を代入してやればUnicodeの開始,終了の値になるのです。

ここで、Xについての範囲を(開始≦X<終了)と表現する必要がある事にも気づきました。

例えばX値で言うと「つ」は(X=17)も(17≦X<18)も同じですが、これらをUnicodeに直したとき

  • 前者は「つ」しか指定できないのに対して
  • 後者は「つ」,「づ」,「っ」を全て指定できる事が分かります。

(16<X≦17)としなかったのは、(X=17)が指定するのは「つ」であり、「づ」や「っ」がその後ろに続くためです。

そのため「て」の直前で範囲を〆める事で狙い通り指定できると考えました。

Step3

ここまでで構築の体系化までを済ませ、最後に変数分離を行う所まで来ました。

ここで、場合分けを残したまま式変形を施すのはエグかったので先にNUを代入して方程式を1通りに決めるとの事でした。

ここでkとcをカウントする方針に変えることが出来た理由をお話して終わりたいと思います。

1番の理由は、僕が簡単にコンピューターに方程式を解かせれる事を知っていたからだと思います。知っていたからこそすんなり妥協出来たのだと考えています。

もう1つ理由を挙げるとすれば、コンピューター関数は数学関数とは別物であると認識した事でしょうか。

まとめると
  • 無理そうでも案外出来る→ある程度足掻いてみよう
  • グループ化は便利→効率化を意識しよう
  • 成り行きだけで案外何とかなる→試行錯誤を重ねよう
  • 知ってる事が多いと有利→勉強しよう
  • 似てても得意分野が違ったりする→あるものは利用しよう

こんな所でしょうか。割とありがちですね

 

おわりに

お疲れ様でした。

ここまで読んでいただき、心より感謝致します。

今回の内容は気に入って頂けたでしょうか。もし役に立った,参考になった或いは為になったのであれば尚幸いです。

ご意見,ご指摘があればコメントよりお願いします。

それではまたお会いしましょう。

「和分の積」演算の性質

電気抵抗でよく見かける「和分の積」ですが、電気分野では非常に多用するが故に演算子まで用意されている程なのです。

和分の積とは次のような演算。

 \color{#ff0000}{R_{1}//R_{2}=\dfrac{R_{1}\times R_{2}}{R_{1}+R_{2}}}

見ての通り和分の積の形をしてます

しかし計算する時、あまり工夫されながち

 

にも関わらず、調べてみると意外にも基本的な性質を結構持ち合わせていたのでまとめていこうと思います。

既に自分で編み出していて、他の人に秘密だった方には申し訳ない。

 

結論から述べると次の性質を持っています

目次

性質
  1. 分配法則「k(R₁//R₂) = kR₁//kR₂」
  2. 交換法則「R₁//R₂ = R₂//R₁」
  3. 結合法則「R₁//(R₂//R₃) = (R₁//R₂)//R₃」
  4. 逆数の公式「1/(R₁//R₂) = 1/R₁ + 1/R₂」
  5. 近似公式「R₁//R₂ ≈ R₁ (R₁<<R₂)」
番外
  • 最後に

 

解説を始めます

1.分配法則

 \color{#ff0000}{k(R_{1}//R_{2})=kR_{1}//kR_{2}}

全体の定数倍が個々の定数倍になるというやつですね。早速証明していきます

証明

 \color{#0000ff}{k(R_{1}//R_{2})=k\times\dfrac{R_{1}\times R_{2}}{R_{1}+R_{2}}\\\ =\dfrac{k\times R_{1}\times R_{2}}{R_{1}+R_{2}}\times\dfrac{k}{k}\\\ =\dfrac{kR_{1}\times kR_{2}}{kR_{1}+kR_{2}}\\\ =kR_{1}//kR_{2}}

[完]

2.交換法則

 \color{#ff0000}{R_{1}//R_{2}=R_{2}//R_{1}}

値が入れ替え可能というやつです。

証明

 \color{#0000ff}{R_{1}//R_{2}=\dfrac{R_{1}\times R_{2}}{R_{1}+R_{2}}\\\ =\dfrac{R_{2}\times R_{1}}{R_{2}+R_{1}}=\\\ R_{2}//R_{1}}

[完]

3.結合法則

 \color{#ff0000}{R_{1}//(R_{2}//R_{3})=(R_{1}//R_{2})//R_{3}=R_{1}//R_{2}//R_{3}}

演算の優先順位が入れ替え可能というやつです。もはや、まるで足し算ですね(本当は全然違うと思います)

証明

 \color{#0000ff}{R_{1}//(R_{2}//R_{3})=\dfrac{R_{1}\times (R_{2}//R_{3})}{R_{1}+(R_{2}//R_{3})}\\\ =\dfrac{R_{1}\times \dfrac{R_{2}\times R_{3}}{R_{2}+R_{3}}}{R_{1}+\dfrac{R_{2}\times R_{3}}{R_{2}+R_{3}}}}

分母と分子にR₂+R₃を掛けます

 \color{#0000ff}{=\dfrac{R_{1}\times (R_{2}\times R_{3})}{R_{1}(R_{2}+R_{3})+R_{2}\times R_{3}}\\\ =\dfrac{R_{1}\times R_{2}\times R_{3}}{R_{1}R_{2}+R_{1}R_{3}+R_{2}R_{3}}}

一方、

 \color{#0000ff}{(R_{1}//R_{2})//R_{3}=\dfrac{(R_{1}//R_{2})\times R_{3}}{(R_{1}//R_{2})+R_{3}}\\\ =\dfrac{\dfrac{R_{1}\times R_{2}}{R_{1}+R_{2}}\times R_{3}}{\dfrac{R_{1}\times R_{2}}{R_{1}+R_{2}}+R_{3}}}

分母と分子にR₁+R₂を掛けます

 \color{#0000ff}{=\dfrac{(R_{1}\times R_{2})\times R_{3}}{R_{1}\times R_{2}+R_{3}(R_{1}+R_{2})}\\\ =\dfrac{R_{1}\times R_{2}\times R_{3}}{R_{1}R_{2}+R_{1}R_{3}+R_{2}R_{3}}}

以上より

 \color{#0000ff}{R_{1}//(R_{2}//R_{3})=(R_{1}//R_{2})//R_{3}=\dfrac{R_{1}\times R_{2}\times R_{3}}{R_{1}R_{2}+R_{1}R_{3}+R_{2}R_{3}}}

[完]

また、優先順位が入れ替え可能とわかったので

R_{1}//R_{2}//R_{3}=\dfrac{R_{1}\times R_{2}\times R_{3}}{R_{1}R_{2}+R_{1}R_{3}+R_{2}R_{3}}

も定義できるだろうという訳です

 

さて、上3つの超基本性質に続き、

和分の積特有の性質について触れていきます

4.逆数の公式

 \color{#ff0000}{\dfrac{1}{R_{1}//R_{2}}=\dfrac{1}{R_{1}}+\dfrac{1}{R_{2}}}

全体の逆数が個々の逆数の和となります。というか和分の積はこの式から導かれています。

中学生にとってはこっちの方が常識なのだけど、和分の積ユーザーにとっては忘れがち

今回はこの式そのものを証明します。

証明

並列回路の図です。

f:id:theEasyPuzzle666:20220605222806j:image

図のようなR₁とR₂の並列接続の合成抵抗を、R₁//R₂で表すとするとオームの法則よりI=V/(R₁//R₂)と表せます。

一方、それぞれの抵抗に着目すると

I₁=V₁/R₁, I₂=V₂/R₂です。

ここでI=I₁+I₂ より先程の式を代入することで

 \dfrac{V}{R_{1}//R_{2}}=\dfrac{V_{1}}{R_{1}}+\dfrac{V_{2}}{R_{2}}が求まります。

V₁=V₂=Vなので

 \dfrac{V}{R_{1}//R_{2}}=\dfrac{V}{R_{1}}+\dfrac{V}{R_{2}}

となって、最後に両辺をVで割ると

 \dfrac{1}{R_{1}//R_{2}}=\dfrac{1}{R_{1}}+\dfrac{1}{R_{2}} [完]

 

長くなった割に中途半端に端折ったので分かりづらいかもしれません。ここを詳しく知りたい場合は他の方の記事が分かりやすいと思います。

一応この右辺を変形していくと

 \dfrac{1}{R_{1}}+\dfrac{1}{R_{2}}=\dfrac{R_{2}}{R_{1}R_{2}}+\dfrac{R_{1}}{R_{1}R_{2}}\\\ =\dfrac{R_{2}+R_{1}}{R_{1}R_{2}}

これが \dfrac{1}{R_{1}//R_{2}}なので

R₁//R₂ はその逆数 \dfrac{R_{1}R_{2}}{R_{2}+R_{1}}

→和分の積が導かれます。

 

5.近似公式

 \color{#ff0000}{R_{1}//R_{2}\approx R_{1} \,\,(R_{1}\ll R_{2})}

R₂がR₁に比べて非常に大きいとき、R₁が支配的になるというものです。

<<はその極端な大小関係を表す記号です。

工夫が云々言いましたが、これは普通に使われます

証明

R₁<<R₂よりR₁+R₂ ≈ R₂なので、

 \color{#0000ff}{R_{1}//R_{2}=\dfrac{R_{1}R_{2}}{R_{1}+R_{2}}\\\ \approx\dfrac{R_{1}R_{2}}{R_{2}}=R_{1}}

[完]

 

最後に

ここまで読んで頂き、有難うございました!