アメリカの大学で奮闘中

アメリカの大学でプログラミングを学ぶべくコンピューターサイエンス学部に留学したものの挫折し数学科に転部した著者が、自分の挫折ポイントを踏まえて数学、プログラミング、アルゴリズムついてできる限り分かりやすく解説してみるブログ。*できる限り記事の内容は技術的な間違いをしないように気をつけていますが、もし間違いがあれば教えていただけると助かります。

JavaScriptの基本文法をpythonと比較してマスターしよう!②

繰り返し処理

 

while文

num = 10

 

while num >0:

    print(num)

    num -= 1

 

while (num >0){

   console.log();

   num -= 1;

}

 

for文

 

for i in range(num):

    print(i)

 

for (let num = 10; num<10; num -=1){

    console.log(num);

}

 

この場合、num -=1をnum --と書くことも可能です。

もしnum+=1の場合はnum ++になります。

 

配列(リスト)

num = [1,2,3]

const num =[1,2,3];

 

要素の取得は同じ

num[i]  *iにはインデックスの番号が入ります

 

要素の更新も同じ

num[i] = (変更したい値) *iにはインデックスの番号が入ります

 

配列の要素の数を取得

len(num)

num.length

 

*配列と繰り返し

pythonだとfor分の中に直接リストを入れることができましたが、JavaScriptではダメなようです

ただし、foreach文というものがあり以下のようなことはできます。

 

num.foreach((i) => { console.log(i); });

 

これはpythonでいうところの

for i in num:

    print(i)

と同じ意味です。

 

 

オブジェクト(辞書、ディクショナリー)

customer = {"id":3, "name":"中山"}

const customer = {id:3, name="中山"};

 

pythonの場合はキーを""で囲わないとNameErrorが起こる

JavaScriptではキーではなく、プロパティーと呼ぶらしい

 

要素の取得

customer["id"]

customer.id

 

要素の更新

customer["id"] = 2

customer.id = 2;

 

続きはこちらから

 

astrostory.hatenablog.com

 

 

JavaScriptの基本文法をpythonと比較してマスターしよう!①

上がpythonの書き方で、下がJavaScriptの書き方です。

出力

print()

console.log();

 

コメントアウト

#

//

 

計算

+ - * / %で、pythonとJavaScriprで変更なし

 

変数

変数の定義の仕方

blog = "アメリカの大学で奮闘中"

let blog = ""アメリカの大学で奮闘中";

 

変数の更新

blog = "IT企業で奮闘中"

blog = "IT企業で奮闘中"

JavaScriptでは変数を更新する際はletをつけない

 

定数

ん!定数って何?ってなりますよね。pythonでは基本的に定数を定義することは

できませんでした。ですがJavaScriptはできます。

 

const author = "Astrostory";

 

定数は定まった数と書くだけあって、author = "Other"のように更新することができないようになっています。

 

 

文字列の結合

"Okay "+name+" , I will do that"

 

`Okay ${name} , I will do that`

 

 

if文①

if num > 10:

    print("10より大きい")

 

if (num > 10){

    console.log("10より大きい");

}

 

JavaScriptはインデントエラーは起こらない

 

if文② ~else~

if num > 10:

    print("10より大きい")

else:

    print("10より大きくない")

 

if (num > 10){

    console.log("10より大きい");

} else {

    console.log("10より大きくない");

}

 

if文② ~else if~

if num > 10:

    print("10より大きい")

elif num > 5:

    print("5より大きい")

else:

    print("5より大きくない")

 

if (num > 10){

    console.log("10より大きい");

} else if (num > 5){

    console.log("5より大きい");

} else {

    console.log("5より大きくない");

}

 

 

真偽値

True False

true false

 

JavaScriptではそれぞれ小文字になっている

 

厳密等価演算子

=== 厳密に等しい

!== 厳密に異なる

 

かつ と または

and or

&& ||

 

Switch文

最近pythonでもできるようになりましたが、馴染みがない人も多いと思うので割愛

 

switch(変数名){

    case 値1:

         処理

    case 値2:

         処理

    default:

         処理

}

 

defaultはif文でいうところのelseに似たようなものになります。

 

pythonを使っていた人がミスしがちな点

文末の ; 

 

続きはこちらから

 

astrostory.hatenablog.com

 

astrostory.hatenablog.com

 

写像(Mapping)とは何か、関数とは何か

アメリカの大学の2年生の秋学期、長かったCalculasのクラスが終わろうとしている時期に、数学の基礎となる証明法や集合理論、数学的記述方法のクラスが始まりました。

 

その時の自分は英語力を未熟で、数学は先生の板書かスライドの数式と教科書の公式を見比べることだけで理解をしていた自分には初めての数学の抽象的な説明を英語で受けることに戸惑い理解することを苦戦していました。

 

そしてまさにその初めて苦労したトピックが写像(Mapping)でした。

 

この記事では、アメリカで数学の授業を受ける方や数学の知識を英語でも知っておかないといけない人に向けて、写像、単射(injective)、全射(surjective)、全単射(bijective)を説明したいと思います。

 

そもそも写像とは?

この答えとしては厳密性や正確性を一旦無視して関数(function)のことだと思ってください。

 

ただし、ここで新たな関数の見方をして欲しいのです。

関数を矢印だと考えてください。さらに言うとAという集合の要素からBという集合の要素に対応させるイメージです。その際には以下のように記述します。

f:A → B

 

例としてf(x)=x+2という関数を考えます。これは言うまでもなくxという値に2を足す関数なのですが、実数の集合から別の実数の集合に対応していると無理やりかもですが言えます。(そもそも実数が集合なんだという方は後々集合についての記事を書く予定ですのでお楽しみに。)

 

この場合、実数R(集合A)から、実数R(集合B)に対応させているという意味を込めて以下のように記述します。集合Bは2を足しても実数であることは変わりないので実数Rです

f:R → R

 

*実数は英語でReal Numberといい、頭文字のRで記述します。

 

この→の性質を考えてみます。そして特徴的なものは名前がつけられています。それが単射(injective)、全射(surjective)、全単射(bijective) になります。

 

以下では先程の関数

f:R → R   f(x)= x+2

g:R → R   g(x)= x^2

を用いて説明していきたいと思います。

 

単射(injective)

単写は集合Aと集合Bの要素が一対一で対応している写像です。

なので、f(x) = 2xは単写になります。その一方でg(x)=x^2はg(x)=g(-x)=x^2と二対一になっているので単射(injective)ではありません。

 

全射(surjective)

全射は矢印が集合Aから集合Bの全ての要素にリーチできる状態になっていることを言います。

f(x)=x+2は、もし集合Bのyという要素が欲しければxについて解いてあげてx=y-2という実数を見つけることができるので全射です。一方でg(x)= x^2はもしg(x)の値がマイナスの時のxの値を探すことができないため、集合Aから集合Bの全ての要素にリーチできる状態ではないので全射ではありません。

 

全単射(bijective)

単写と全射の両方を満たすものを全単射と呼びます。なのでf(x)=x+2は全単射と言えます。

 

余談:写像と関数の違い

こちらのサイトには以下のように記述されていました。

mathlandscape.com

 

結論,両者の違いは基本的にないと思って差し支えないです。
強いて言えば,終域が数やそれに関連するものであるとき,「関数」といい,そうでないとき「写像」ということが多いです。

 

実際に大学の授業でも(少なくとも学部生のうちは)特に区別することなく理解していても問題ありませんでした。

Web開発かアプリ開発かまだ決め切れていないエンジニアはJavaScriptを学びなさい

少し攻めたタイトルになってしまったのですが、今回の記事ではプログラミングを学び始めたor就活でエンジニア就職をする予定だけど何を勉強すればいいか分からない人で、特にWEB開発とアプリ開発で迷っている人をターゲットにしています。

 

結論から言うと、迷っている人はJavaScriptを勉強すると良いと思います。理由はweb開発にもアプリ開発もJavaScriptで作ることができるからです。

 

そもそもJavaScriptとは

1995年にネットスケープコミュニケーションズのプログラマーだったブレンダン・アイク氏が開発した言語です。

 

HTML、CSS(WEBサイトの見た目を作る言語)で書かれた画面に動きをつけたりできます。例えばwebサイトのトップの画像が時間が経てば横にスライドして画像が変わるものとかありますよね。あのようなものはJavaScriptで実装できます。

 

また、3Dに動きをつけることもできることから、VRなどにも使われたりもあるようです。(ただもしVRの開発者などを目指す場合はJavaScriptより先に学ぶ優先度の高い技術があるとは思いますが)

 

WEB開発とJavaScript

上述した通りJavaScriptは画面に動きをつけるためのものだったのですが、今はサーバーサイドも書けるようなったため必要性がさらに増しています。

 

サーバーサイドのプログラムとは、サーバ側から行う処理に対して必要なプログラムのことですが、具体例としては、検索単語を入れたらその結果を返すとか、データーベース(データを保存するところ)に問い合わせデータを入れるとか、同じドメインの別のwebページに飛ばす(ルーティング)などになります。

 

なのでJavaScriptと、Node.jsやReactなどのライブラリー、フレームワークさえできればweb開発が可能です。

 

アプリ開発とJavaScript

ここでいうアプリはモバイルアプリを想定しています。

 

元々iosのアプリはObjective-C(現在はSwift)、AndroidはJavaで別々で書かなくてはいけなかったのですが、最近は1つの言語でios用、Android用の両方を開発できるようになりました。

 

その言語がJavaScriptである開発ツールをここでシェアできればと思います。

 

Expo

ExpoはFacebookが開発したReactNativeやその開発ツールです。JavaScriptでios、Androidのモバイルアプリの開発を行えます。

 

expo.dev

 

Monaca

Monacaは日本の会社が提供している開発ツールで、web上のエディタで開発ができることと、公式サイトが日本語であることからお手軽なところがメリットです。

 

ja.monaca.io

 

最後に

実は僕もモバイル開発にJavaScriptが使えることをここ最近知った身で、もっと早く知っていたら身を引き締めてJavaScriptの勉強ができたのにと感じていました。もし読者がJavaScript勉強中の方でしたらより一層モチベーションを上げて勉強していただけたら幸いです。またどの言語を学ぶか検討中の方は判断材料として参考にしていただければと思います。僕もまだまだ学習中の身ですが、需要がありそうでしたら普段のアルゴリズムや数学に加えてこのような実践的な開発についても書いていこうと思います。

 

Pythonの文法が分かって、新たにJavaScriptを勉強したい方向けの記事

 

astrostory.hatenablog.com

 

 

参考文献

 

JavaScriptの歴史【紆余曲折を経たプログラミング言語】 – 株式会社ライトコード

 

【2020年版】人気のNode.jsライブラリ・フレームワーク厳選まとめ | あしたのチームTechBlog

マルコフ連鎖②~グラフを考える~

前回の記事の続きです。

 

astrostory.hatenablog.com

 

この記事ではマルコフ連鎖をグラフとして見ていきます。なお、今回も例は前回の記事の天気の例を利用します。

 

簡単に再度説明しますと

 

晴れ、曇り、雨という3つの状態があり、そのいずれかの状態から別の状態に遷移します。

遷移の確率はそれぞれいかになります。

晴れ→晴れの確率をp1、曇り→晴れの確率をq1、雨→晴れの確率をr1

晴れ→曇りの確率をp2、曇り→曇りの確率をq2、雨→曇りの確率をr2

晴れ→雨の確率をp3、曇り→雨の確率をq3、雨→雨の確率をr3

 

グラフとして見る

マルコフ連鎖をグラフとして見ると以下のようになります。

 

f:id:Astrostory:20220217155251p:plain

 

グラフの特徴として、マルコフ連鎖はループを含む(かもしれない)有向グラフになります。

 

遷移行列

グラフには隣接行列という、行列にそれぞれのノードをとってどことどこのノードがつながっているかの情報を0と1であらわして、隣接状況を表現する隣接行列というものがありました。

 

もしご存知でない方はこちらもご参考ください。

astrostory.hatenablog.com

 

マルコフ連鎖にもそのような行列が存在します。マルコフ連鎖の隣接行列は、状態の遷移を表すため遷移行列と呼ばれ、隣接しているか否かの0,1でなく、0か遷移する時の確率で示します。

 

天気の例での遷移確率は以下のようになります。

   A   B   C

A   p1 q1  r1

B   p2 q2 r2

C   p3 q3 r3

 

これ今ある状態(行)から次(tからt+1)に遷移する状態(列)の確率をまとめていますが、この行列式を二乗すればtからt+2の遷移行列になり、この行列式を三乗するとtからt+3の遷移行列になります。

 

これってプログラムで扱うには便利な性質だと思いませんか?

 

にほんブログ村 教育ブログ プログラミング教育へ
にほんブログ村

マルコフ連鎖①〜グラフ理論と確率〜

マルコフ連鎖というグラフ理論を用いた確率の考え方があり、これはプログラムの実装も可能で便利だと思うのでこの記事で詳しく説明できればと思います。

 

いつものように数学的な厳密性は少し欠けていても分かりやすい記事を目指します。

 

マルコフ連鎖とは

マルコフ連鎖とはt(時間)が離散的なマルコフ過程の一種です。

 

マルコフ過程とは、次に起こる事象が今と過去の状態に依存することなく、現在の状態のみで決まる確率過程のことをいいます。

 

現在も状況のみで決まるというポイントが確率の表記を簡単に、コンピューターサイエンスに応用しやすくしているポイントだと思います。

 

実際にマルコフ連鎖を表現する数式は以下のように記述することができます。

P{xn = axm = am, m < n} P{xn = axn1 = an1}

(n-1を現在としてみれば)t =nでx=aとなる状態に来るまでt=m(0<=m<=n)の過程があったにも関わらず、その確率はt=n-1のみの条件付き確率になっている。すなわち現在の状態によって未来の状態が決まる確率という式になっているかと思います。

 

t=n+1の確率をt=nの時の状態で決まるというふうに書いても大丈夫です。

 

表記はいくつか方法があるかと思います。

 

例えば

𝑃 (𝑋𝑛+1 = 𝑗 | X𝑛 = 𝑖, X𝑛−1 = 𝑖𝑛−1,...,X0 = 𝑖0) = 𝑝(𝑖,𝑗)

t=0~nの時にi_0 ~ i_nの状態経てXn+1の時にjになるのは、iとjのみの要素で決まるという意味の式です。

 

具体例

 

例えば、マルコフ連鎖の説明でよく出てくる天気の例を出したいと思います。

晴れの事象をA、曇りの事象をB、雨の事象をCとし、

晴れ→晴れの確率をp1、曇り→晴れの確率をq1、雨→晴れの確率をr1とします。

 

そうすると、

次の日腫れる確率は以下になる。

今日晴れの時 ... p・An

今日曇りの時は ... q・Bn

今日雨の時は ... r・Cn

 

なので、このように3つの状態から晴れになる遷移をするマルコフ連鎖の確率Pn+1は以下のように表されます。

Pn+1 = p1・An + q1・Bn + r1・Cn

 

さらに

晴れ→曇りの確率をp2、曇り→曇りの確率をq2、雨→曇りの確率をr2

晴れ→雨の確率をp3、曇り→雨の確率をq3、雨→雨の確率をr3とすると

 

次の日曇りになる確率と次の日雨になる確率は以下のようになる。

Qn+1 = p2・An + q2・Bn + r2・Cn

Rn+1 = p3・An + q3・Bn + r3・Cn

 

このような確率過程をマルコフ連鎖といいます。

 

グラフ理論ともう少し絡めてマルコフ連鎖を実装する時に役立つ知識を紹介している記事も興味のある方はどうぞ。

astrostory.hatenablog.com

 

クイックソート(Quicksort)を解説してみた by Python

 

クイックソートとはデータの集合をある決まりに従って並び替えるソートアルゴリズムの一種です。クイックソートはクイックと付いているだけあって早く処理できる方法になります。

 

今回は

array = [5,4,6,9,2,7,8,1,3]    →   array = [1,2,3,4,5,6,7,8,9]

arrayの中身をリストを数字の小さい順に並び替えるクイックソートを考えます。

 

ちなみにもしリスト型のメソッドを使うなら array.sort() で小さい順に並び変わります。

 

アルゴリズム

簡単にまとめると

基準値を決めてそれより小さいグループ大きいグループに分ける、小さいグループはさらに小さいグループとそれよりは大きいグループに分け、大きいグループはさらに大きいグループとそれよりは小さいグループに分けていく。それを繰り返して、グループの要素が一個になるまで行い、その全てのグループを連結し直すと並び替えられたリストになっている。

 

f:id:Astrostory:20220207161154p:plain

 

リストを分割(quicksort 関数)

1、元与えられたリストでPartition関数を呼び出して分割する

 

2、分割された左側(数が小さい方)と右側(数が大きい方)でまた別々にPartition関数を呼び出す。

 

3、2番がリストの要素の数が1つになる手前まで繰り返される(if l>rの条件)

 

 

リストを並び替え(Partition 関数)

1、pivotというデータの大小を比べる基準になる変数をソートするリストの中から決定します。

リストの最初や真ん中、最後のデータかリストのはじめのデータをpivotとしていたり、任意の3つのデータのメジアンをpivotとしているコードもみたことがあります。

 

2、pivotより左側のデーったはpivotのそれより小さく、右側のデータはpivotのそれより大きいことをループを使ってチェックしていきます。

 

3、左側のデータの方が大きかったり、右側の方が小さかった場合、それら二つをスワッピング(交換)します。

 

4、3の操作の終わったリストを[pivotとそれより前の要素を含むリスト]、[pivott以降の用を含むリスト]の二つに分割して、再帰させ1−3をまた繰り返されます。

最後に要素が1つしかないリストになるまで繰り返されます。

 

コード

def quicksort(arr):

    qs(arr, 0, len(arr) - 1)

 

def qs(arr, l, r):

    if l >= r:

        return

    p = partition(arr, l, r)

    qs(arr, l, p - 1)

    qs(arr, p + 1, r)

 

def partition(arr, l, r):

    print("arr",arr[l:r+1])

    pivot = arr[r]

    print("pivot is", pivot)

    i = l - 1

    for j in range(l, r):

        if arr[j] < pivot:

            print("In-Small", arr[j])

            i += 1

            print("Swap point", i)

            arr[i], arr[j] = arr[j], arr[i]

    arr[i + 1], arr[r] = arr[r], arr[i + 1]

    return i + 1

 

 

a1 = [5, 4, 6, 9, 2, 7, 8, 1, 3]

quicksort(a1)

 

実行結果とその解説

実行結果

arr [5, 4, 6, 9, 2, 7, 8, 1, 3]

pivot is 3

In-Small 2

Swap point 0

In-Small 1

Swap point 1

arr [2, 1]

pivot is 1

arr [9, 5, 7, 8, 4, 6]

pivot is 6

In-Small 5

Swap point 3

In-Small 4

Swap point 4

arr [5, 4]

pivot is 4

arr [8, 9, 7]

pivot is 7

arr [9, 8]

pivot is 8

解説

1個目の分割と並び替え

arr [5, 4, 6, 9, 2, 7, 8, 1, 3]

pivot is 3

In-Small 2

Swap point 0

In-Small 1

Swap point 1

まだ分割する前なので、与えられた配列は一番最初のリストそのものです。

pivot(大小を比べる基準の数)は一番右の3が選ばれ、3以下の1,2は左のインデックス0と1の場所の値(5,4)と交換させられます。(arr[i], arr[j] = arr[j], arr[i])

そして最後にpivotの3を交換した次の値(インデックス2)に配置して1つ目の分割は終わります。( arr[i + 1], arr[r] = arr[r], arr[i + 1])

リストの分かれ方は以下になります。

[2,1] | 3 | [9,5,7,8,4,6]

 

2個目の分割と並び替え

arr [2, 1]

pivot is 1

1つ目の分割の結果の左側が最初再帰にかけられます。

pivotは一番右の1が選ばれますが、1がリストの中で一番小さいため交換は起こらず、pivotと先頭の数が交換させられます。

リストの分かれ方は以下になります。

1 | [2]

 

3つ目の分割と並び替え

arr [9, 5, 7, 8, 4, 6]

pivot is 6

In-Small 5

Swap point 3

In-Small 4

Swap point 4

1つ目の分割の結果の右側が再帰にかけられています。

pivotは一番右の6が選ばれます。5と4が6より小さいため、リストのインデックス3,4に小さい数が集められ、pivotより小さいグループ、pivot、pivotより大きいグループに分けられます。

*arrは常に要素全体を持ったリストであり、rとlの引数でインデックスを操作して左右を分割しているため、この3つ目の分割と並び替えは前回のリストの右側に当たるため、[1,2,3,〇,〇]の○に該当する場所が数を入れ替える場所になります。

リストの分かれ方は以下になります。

1 | [2] | 3 | [5,4] | 6 | [8,9,7]

 

4、5つ目の分割と並び替え

arr [5, 4]

pivot is 4

 

arr [8, 9, 7]

pivot is 7

これらは先ほどの結果の [5,4] と[8,9,7]をさらに並び替え&分割している様子になります。

2番目の分割と並び替えと全く同じことが行われているので分かりやすいかと思います。

リストの分かれ方は以下になります。

1 | [2] | 3 | 4 | [5] | 6 | 7 |[9,8]

 

6つ目の分割と並び替え

arr [9, 8]

pivot is 8

[9,8]のリストを並び変え&分割を行っております。

リストの分かれ方は以下になります。

1 | [2] | 3 | 4 | [5] | 6 | 7 | 8 | [9]

これにより、1~9まで順番に並んだことになります。

 

参考文献

英語ですが、図と実際のコードを動画で解説しておりとても分かりやすくておすすめです。

A Complete Overview of Quicksort (Data Structures & Algorithms #11) - YouTube

にほんブログ村 教育ブログ プログラミング教育へ
にほんブログ村