[color=#0000ff][b][size=150][b]このワークシートは[url=https://www.geogebra.org/m/twxxx3yq]Math by Code[/url]の一部です。[br][/b][br][br]関数は集合Xの要素xから集合Yの要素yへの対応づけだ。[br][/size][/b][/color]対応がつけばよいだけなのに、対応を式に表すことができると考えてしまいがちだ。[br]f :: X→Y[br]f (x) = expr(x)[br]中学数学で学んだ1次関数、2次関数のイメージが強いためか、[br]関数というと、[color=#0000ff][b]y=xの式という、計算操作のイメージ[/b][/color]がつきまつ。[br][br]しかし、結果としてのグラフイメージで関数を俯瞰してみよう。[br]すると、[color=#0000ff][b]関数はXとYの直積空間(X-Y座標平面)の要素の点(x,y)のあつまり、部分集合[/b][/color]という風にとらえることもできる。[br][br]y=2xという関数は、この関数を満たす点と考えると、順序対、タプル(x,y)のリスト[br]と考えることもできるね。[br]連続量に近いイメージがほしければ、xの範囲を細かく区切ると良い。[br][color=#0000ff]#[IN]julia[br]#============================[br]F=[(x,2*x) for x in 1:10][br]G=[(x,2*x) for x in 1:0.001:10][br]#============================[br][/color][OUT][br]10-element Vector{Tuple{Int64, Int64}}:[br] (1, 2)[br] (2, 4)[br] (3, 6)[br] (4, 8)[br] (5, 10)[br] (6, 12)[br] (7, 14)[br] (8, 16)[br] (9, 18)[br] (10, 20)[br][OUT][br]91-element Vector{Tuple{Float64, Float64}}:[br] (1.0, 2.0)[br] (1.1, 2.2)[br] (1.2, 2.4)[br] (1.3, 2.6)[br] (1.4, 2.8)[br] (1.5, 3.0)[br] (1.6, 3.2)[br] (1.7, 3.4)[br] (1.8, 3.6)[br] (1.9, 3.8)[br] (2.0, 4.0)[br] (2.1, 4.2)[br] (2.2, 4.4)[br] ⋮[br] (8.9, 17.8)[br] (9.0, 18.0)[br] (9.1, 18.2)[br] (9.2, 18.4)[br] (9.3, 18.6)[br] (9.4, 18.8)[br] (9.5, 19.0)[br] (9.6, 19.2)[br] (9.7, 19.4)[br] (9.8, 19.6)[br] (9.9, 19.8)[br] (10.0, 20.0)[br][br]すると、1対1にこだわらなければ、xの剰余を対応させたり、[br][color=#0000ff]xの値と無関係に乱数を作ってzipで順序対(タプル)を作ったり[/color]と[br]関数は自由だ。[br][br][color=#0000ff][b][size=200]zipを使うと、関数も作れるし、グラフもすぐかけるね。[br][/size][/b][br]#[IN]julia[br]#============================[br]H=[(x,x % 3) for x in 1:10][br][/color][color=#0000ff]#============================[br][OUT][br]10-element Vector{Tuple{Int64, Int64}}:[br] (1, 1)[br] (2, 2)[br] (3, 0)[br] (4, 1)[br] (5, 2)[br] (6, 0)[br] (7, 1)[br] (8, 2)[br] (9, 0)[br] (10, 1)[br]#[IN]julia[br]#============================[br]xs=Vector(1:10)[br]ys=rand(10)[br]z=[(x,y) for (x,y) in zip(xs,ys)][/color][br]#============================[br][OUT][br]10-element Vector{Tuple{Int64, Float64}}:[br] (1, 0.20169081026514768)[br] (2, 0.17422295843712776)[br] (3, 0.25178803264424066)[br] (4, 0.5264239612886585)[br] (5, 0.4820281573212978)[br] (6, 0.23582173409057716)[br] (7, 0.06452661349364275)[br] (8, 0.6707651637338825)[br] (9, 0.3189198173371426)[br] (10, 0.4016041332227487)[br][br][b][br][/b]
[b][size=150]<シーザー暗号とは>[br][/size][/b]シーザー[color=#9900ff][b]暗号[Cipher][/b][/color]というものがある。[br][br]これって、ルールは単純で、[br]文字xに対して、文字コードy=f(x)を対応させる。[br]f(x)は数値だから、それに定数sを足す。[br]そして、文字コードsに対する文字をf-1(x)で求めたものをzとしよう。[br]これが暗号化関数Cだ。[br][br]これを、入力した文字列Xの文字xすべて対してzを求めて出力したものが文字列Zとなる。[br]つまり、暗号化はC :: X→Zとかけるね。[br][br]とうことは暗号解読はその逆関数C[sup]-1[/sup] ::Z→Xとかくことができるはずだ。[br][br][b][size=150]<暗号化と復号化を比べると>[br][/size][/b]それでは、暗号を作る関数Cと暗号を解読(復号)する逆関数C[sup]-1[/sup]を作ってみようか?。[br]しかし、この発想には無駄がある。[br][br]暗号化のときに、文字コードを+sしているとしたら、[br]復号化のときは、文字コードをーsすればよいだけだ。[br]だったら、[b]暗号と復号の両方に使える関数Ci[/b]を作った方がよいことがわかるね。[br]シフト数をshift 、入力文字をxとすると[br][br][color=#0000ff][b][size=150]コード化::Char→Int x -> y = codepoint(x)[br]シフト:: Int →Int y -> z = y + shift[br]デコード化:: Int→Char z -> d=Char(z)[br][/size][/b][/color][br]この3ステップを合成した関数がCiになるね。[br][br][b]<実装しよう>[br][/b][color=#0000ff]#julia[br]#============================[br]Int(codepoint('A'))[br]#============================[br][/color][OUT][br]65[br][color=#0000ff]#============================[br]Char(65)[br]#============================[br][/color][OUT][br]'A': [br]このように、コード化とデコード化はできることがわかる。[br]英数字、つまり、アスキー文字に限った暗号だとすると、[br]コード番号にshiftを加算してずらそう。[br]ただ、たすのではなく、Aが0番になるようにして、[br]からshiftをたして、それでも65を超えた番号は[br]振り出しのAから順にぐるぐる回るようにしたい。[br][color=#0000ff]#julia[br]#============================[br]Ci(shift::Int, x::Char)::Char = Char((Int(codepoint(x)) - 65 + shift) % 65 + 65)[br]Ci(0,'A'),Ci(1,'A'),Ci(2,'A'),Ci(3,'A')[br]#============================[br][/color][OUT][br]('A', 'B', 'C', 'D')[br][br]では、もっと先の文字も含めて、暗号と復号がうまくいくことを確認しよう。[br][color=#0000ff]#julia[br]#============================[br]Target = "ABCDE PQRSTU abcde,.xyz";[br][br]println(Target)[br]Ciphered=join([Ci(5,x) for x in Target] )[br]println(Ciphered)[br]Recovered=join([Ci(-5,x) for x in Ciphered] )[br]println(Recovered)[br][/color][color=#0000ff]#============================[br][/color][OUT][br]ABCDE PQRSTU abcde,.xyz[br]FGHIJ%UVWXYZ%fghij13}~[br]ABCDE PQRSTU abcde,.xyz[br][color=#0000ff][br]#julia[br]#============================[br]Target = "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG";[br][br]println(Target)[br]Ciphered=join([Ci(5,x) for x in Target] )[br]println(Ciphered)[br]Recovered=join([Ci(-5,x) for x in Ciphered] )[br]println(Recovered)[br][/color][color=#0000ff]#============================[br][/color][OUT][br]THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG[br]YMJ%VZNHP%GWT\S%KT]%OZRUX%T[JW%YMJ%QF_^%ITL[br]THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG[br]