#acl hogas:admin,read,write,delete,revert All:read #format gfm # プログラミング講習 by hogas 「プログラミング」について、ふわっとでも理解をしてもらえればと思います。 #### 事前準備 Google Chrome と Sublime Text をインストールしておいてください - [Google Chrome はここから](https://www.google.co.jp/chrome/browser/desktop/index.html) - [Sublime Text はここから](https://www.sublimetext.com/3) - ブラウザとエディタならなんでもいいですが、僕は上記のものでやります - [使うファイルはここから](https://www.mma.club.uec.ac.jp/~hogas/progsem.zip) - ブラウザでアクセスすればダウンロードされるはず ## 本日のメニュー - お店探し: 導入 - お通し: 準備 - 前菜: 第一歩 - スープ: 閑話 - メインディッシュ 1~6 品: 主な内容 - デザート: 結び ## お店探し: 導入 ### 身近のお話 PC、スマートフォン、自動改札機、ラジコン、... 電気回路とか、プログラムとかで動いています ### プログラム 機械を動かすための **命令書** 書といっても言葉は色々 ここではソフトウェアを扱います ### プログラミング 機械を思うように動かして嬉しくなること そのためにプログラムを書くこと **機械** がわかるのは、電気の ON/OFF これを **0** と **1** で表現して制御するのを **人間** がわかる **言語** というもので包んであります これによって人間から機械への命令の橋渡しができています ``` 人間 --> 言語 --> 0 と 1 --> 電気 --> 機械 ``` ### プログラミング言語 人間が読んでわかる言葉から 機械が読んでわかる言葉に **変換** することができる言語 (日本語は機械が読んでわかる言葉に変換することができません) 色々な言語がありますが、最終的には 0と1に変換されて機械に与えられます (ある言語から、一旦別の言語へ変換されたりも) ### ソースコード 書かれたプログラムのこと ### プログラミングの三構造 プログラミングするにあたって、3種類の構造がある、という考え方があります #### 順次 プログラムに書かれた順番通りに、命令を実行する - 例: 「蛇口を開く」「手を前に出す」 - 順番にやらないと手が洗えない #### 分岐 条件によって異なる処理をする - 例: 「眠ければ、寝る」「そうでないなら、課題をやる」 - 寝るか、課題をやるか、ふたつにひとつ #### 反復 処理を繰り返す - 例: 「水が止まるまで、蛇口を締める」 - 何回も蛇口を閉めて、水が止まったらやめる この三構造を基本としてプログラミングをします ### JavaScript プログラミング言語のひとつ WebのHTMLページで使ったりすることが多い 最近は様々な用途で使います よく略して JS 、ジャバスクなどと呼ばれます ### なぜJavaScriptをやるか プログラムの感覚がわかりやすい(主観) 所謂おまじないが少なくて済む(主観) (言語処理系は詳しく決まっているし進化し続けている、のですが僕は詳しくありません) ### わからない場合 周りの先輩とかに聞いてください 近くの人に教わっても問題ありません [Slack \#fresh\_seminar\_room](https://uecmma.slack.com/messages/fresh_seminar_room) にも質問OKです ### わかる場合 楽しんでください ## お通し: 準備 ### 使うもの #### ファイル playgroundディレクトリに入っているファイルを使います ##### progsem.html ここにすでに progsem.js が読み込んであります これは編集しなくてOK (してもいいけど) ##### progsem.js このファイルにソースコードを書いていきます ##### confirm.js JavaScriptファイルが正しく読み込めるか確認するように(僕が)書いたテストなファイル Consoleに最初に時刻を出すようにしたりしました これは編集しなくてOK (してもいいけど) #### ブラウザ 僕は **GoogleChrome** を使います FireFox や Edge でも それ以外でも構いません ##### 表示場所 **Console** - F12 とか Ctrl + Shift + I とか - Cmd + Option + I とか - 右上メニューとか で開く `MMA Fresh Seminar : Tue May 30 2017 04:30:12 GMT+0900 (東京 (標準時))` のような 「MMA Frash Seminar : 日付時刻」 が出ていればOK #### エディタ 僕は **SublimeText** を使います Atom や Vim や Emacs でも、その他でも構いませんが メモ帳 では大変で、Microsoft Office Word では不可能です ダウンロードは→ [ここ](https://www.sublimetext.com/3) ←からしてください - 「portable version」をダウンロードするとインストール無しにすぐ使えます #### 使うものの準備 ##### ブラウザで progsem.html を開く - ドラッグ & ドロップ とか - Ctrl + O とか Cmd + O とか ##### 準備ができたか確認 1. `We are MMA!` と出ていれば、HTMLは読み込めている 1. `JavaScript is ready for seminar.` と出ていれば、JavaScriptも動いている ##### エディタで progsem.js を開く - ウィンドウのメニューとか - ドラッグ & ドロップ とか - Ctrl + O とか Cmd + O とか ```js // progsem.js // This is MMA fresh seminar - programming ``` と書いてあるのがエディタで見えたらOK --- ここからは、自分の思った通りに機械を動かします。 ## 前菜: 好きな文字を表示する - progsem.js を以下のように編集する ```js // progsem.js // This is MMA fresh seminar - programming console.log(3) ``` こう書いたら **保存** して、ブラウザを **再読込** すると **Console** に `3` が表示される - `console.log()` は `()` 内に入れたものを Consoleに出力(表示)します ```js // progsem.js // This is MMA fresh seminar - programming console.log('A') ``` こう書いたら **保存** して、ブラウザを **再読込** すると **Console** に `A` が表示されます 「A という文字」は `'A'`と書く 単に `A` とだけ書くと別の意味になります(後述) 数字はそのまま`3`でOK ```js // progsem.js // This is MMA fresh seminar - programming - console.log('MMA') ``` 何文字でもいけます **保存 && ブラウザ再読込** で実行です ## スープ: 閑話 progsem.jsに最初から入っていた2行は、コメントといいます ```js // progsem.js // This is MMA fresh seminar - programming ``` `//` から行末までの文字は、プログラムとしては無視されます つまり、プログラムを気にせずに、人間が好きなことを書くことができます なので書いていなくても構いませんが、 よく「ここに何が書いてあるのか」「これは何を意味するのか」 を書いたりします 以下でも編集するのは同じく progsem.js なので、コメント文の部分は省略します ## 1品目: 足し算 計算機なので計算したい ```js 2 + 3 ``` こうすると、式 `2 + 3` が実行されて `5` になります が、 **保存 && ブラウザ再読込** しても `5` と表示されません ので、計算結果を表示するようにします 前菜で使った `console.log()` の中に入れます ```js console.log(2 + 3) ``` **保存 && ブラウザ再読込** すると `5`と表示されます - 「式 `2 + 3` が実行されて `5` になる」というようなことを「式が評価される」と言ったりします それなりに大きい数でもできます ```js console.log(12345 + 67890) ``` **保存 && ブラウザ再読込** すると `80235`と表示されます (正しいか計算してみてください) 「それなりに」と書いたのは、 - 実行環境の限界とか - 計算機の限界とか を意味する気持ちです べらぼうに大きい、計算機の限界を超えるような数は、 計算機が覚えきれなかったりして、計算できません それでも、大分大きな数を扱うことができるので、 そうなると、人間がそらで計算したり手計算したりするより、 **速くて正確** です ## 2品目: 四則演算 足し算はできたので、四則演算すべてをやっていきましょう ```js console.log(2 + 3) // 足し算 console.log(23 - 45) // 引き算 console.log(12 * 12) // 掛け算 console.log(100 / 3) // 割り算 ``` これを実行すると、 ``` 5 -22 144 33.333333333333336 ``` と表示されます - **実行する** には、ここでは **エディタでjsファイルを保存 && ブラウザでHTMLを再読込** 見てわかる通り、四則演算の記号(演算子という)は、それぞれ - 足し算 `+` - 引き算 `-` - 掛け算 `*` - 割り算 `/` です (掛け算と割り算は見慣れないかもしれませんが、計算機の都合で、 色々な言語でもほとんど同じく、この記号を使います) #### お冷: 例題 次の得点たちの平均を求めてみます - 得点: 67, 45, 89, 60, 98 平均を求めるには、 - すべてを足し算して - データの個数で割り算する ので、 `(67 + 45 + 89 + 60 + 98) / 5` のように計算します - 括弧をつけずに `67 + 45 + 89 + 60 + 98 / 5` とすると - `67 + 45 + 89 + 60 + (98 / 5)` となってしまいます (算数・数学と同じです) - 掛け算・割り算は、足し算・引き算よりも **優先順位が高い** 計算結果を表示したいので、プログラムには次のように書いてみます ```js console.log((67 + 45 + 89 + 60 + 98) / 5) ``` `console.log()` と数式で、括弧が2組ありますが、 気にする必要はありません - ここは数学にならってしまうと中括弧や大括弧にしがちですが、それはしません - いくつになっても小括弧を書きます - 中括弧・大括弧は、別の役割があります これを実行すると、次のように結果が表示されます 暇な時に手計算して、本当かどうか確認してみてください ``` 71.8 ``` 平均得点は 71.8 点だった、ということです ## 3品目: 変数 次のようなとき、プログラムを書くにあたって、人間が面倒を被る場合が出てきます 例: ひとつ 123 円のリンゴを 3 こ買い、 次にひとつ 987 円のミカンを 2 こ買ったときの、 それぞれの時点での、総支出を計算したい 最初の時点では `123 * 3` と計算でき、次の時点では `123 * 3 + 987 * 2` と計算できます これらの結果を表示します - プログラムは、順次実行されるので、次のように書けます - 2回表示するということ ```js console.log(123 * 3) console.log(123 * 3 + 987 * 2) ``` これを実行すると結果が表示されます ``` 369 2343 ``` つまり最初のリンゴの時点では 369 円、 ミカンの時点では合わせて 2343 円を支出しています ここで、このプログラムを **もう少し賢く** 書く方法があります **変数** というものを使います たとえば次のように使い始めます ```js let a ``` これは **変数宣言** と呼ばれるもので、「これからこの名前の変数を使います」という **宣言** です JavaScript では `let` と書いてから変数名を書きます 今は `a` という名前の変数を使うことにしています - `let` などの変数宣言で使う言葉は、言語ごとに違う場合が多いです - JavaScript には、他に `const` `var` というのもありますが、それぞれ役割があります - 今回は `let` しか使いません プログラミングでいう変数というのは、数学でいうそれとは捉え方が少し違います よく使われる表現は「値を格納しておく箱」です 今回のプログラムでは、同じ計算を 2 回しています `123 * 3` `123 * 3 + 987 * 2` ここを賢くしたい まず、変数を(好きな名前で)宣言します ```js // 総支出の意味でわかりやすく sum という名前にしてみる let sum ``` 総支出を計算次第、変数に格納するようにします 格納するには、 `=` を使います `sum = 123 * 3` 気持ちとしては、「 `sum` に格納します、 `123 * 3` の結果を」 という感じ ここで変数 `sum` を表示してみると、計算結果が格納されていることがわかります `console.log(sum)` ここまでをまとめると、プログラムは以下のように書けます ```js let sum sum = 123 * 3 console.log(sum) ``` 実行すると、以下のように表示されます ``` 369 ``` これは最初のリンゴの時点の総支出です ここからミカンを買いますが、総支出は 「今までの総支出 + ミカンの分」 つまり `sum + 987 * 2` なので `sum = sum + 987 * 2` と書きます 気持ちとしては、「 `sum` に格納します、 `sum + 987 * 2` の結果を」 新しい総支出を計算し、それを格納しています つまり、「 `=` の右側(右辺)の結果を出してから、 `=` の左側(左辺)へ格納する」ということが行われています - 数学でのイコールとは扱いが違うので注意 ということで、プログラムは以下のように書きます ```js // 変数宣言 let sum // リンゴの時点の総支出計算、格納 sum = 123 * 3 // リンゴの時点の総支出表示 console.log(sum) // ミカンの時点の総支出計算、格納 sum = sum + 987 * 2 // ミカンの時点の総支出表示 console.log(sum) ``` - 見やすく、コメントと空行を入れてみました - コメントも空行も適宜入れてOKです 実行すると、次のように表示されます ``` 369 2343 ``` これで、先のものと同じ結果が得られました ちなみに、「賢く」と言っておきながら書く量が増えていますが、 買うものが増えると途端にありがたみが出てきます 例: 123 円 * 2こ 、345 円 * 3こ 、987 円 * 4こ 、765 円 * 5こ 、…… #### お冷: 文字列と数値と変数 最初の方で、「 `'A'` と `A` とは違う意味になります」と書きましたが、 つまり `'A'` は文字列で、 `A` はそういう名前の変数、という扱いになるという意味です ```js let A A = 10 console.log(A) console.log('A') ``` を実行すると次のように表示されます ``` 10 A ``` JavaScript で変数名に使えるのは、次の字から始まるものです - アルファベット - アンダースコア( `_` )、ドル記号( `$` ) 後に続く字は上のものに加えて数字でも構いません なので、 `hoge` `_hoge` `h_o_g_e` `$hoge` `hoge0` `h35` はOK ただし、その中でも次のものはできません - **予約語** という、言語自体で先に決めてある言葉 - `let` とか `for` とか - `let` という変数を作れてしまったら、言語の機構が「変数宣言?変数名?」と見分けられないので、禁止されている - `let let` とか書くとエラーが出ます ## 4品目: 分岐 最初に出てきた **プログラミングの三構造** について、すでに **順次** をやりました ここではさらに **分岐** をしてみます 例: 例: 134 円のクッキー 2つ、 584 円のチョコ 1つ、 266 円の紙 1つを 所持金 1000 円で買えるかどうかを気にしてみます とりあえず、総支出を計算して表示するプログラムを書きます ```js let sum sum = 134 * 2 + 584 + 266 console.log(sum) ``` - 何気なしに変数を使っていますが、この時点では `console.log()` に直書きしても同じですね 実行すると、次のように表示されます ``` 1118 ``` つまり持っているお金 1000 円を越えてしまうことがわかります ここで、 1000 円以内に収まるときは `'OK!'` 、収まらないときは `'NG...'` を表示する、というプログラムにしてみたいとします 「~のときは……、そうでなくて~なら……」というのは、 **条件** とよく呼ばれます 条件によって、実行する命令を変えることを、条件分岐といいます JavaScript では、 `if` という文を使います (多くの言語で同じく `if` を使います) 今回やりたい条件分岐は、「1000 円以内に収まるか、収まらないか」なので、以下のように書きます ```js if (sum <= 1000) { // 1000 に収まるか console.log('OK!') } else { // 収まらなければ console.log('NG...') } ``` `if` は - `if (条件) {そのときの命令たち}` - `if (条件) {そのときの命令たち} else {そのときの命令たち}` - `if (条件) {そのときの命令たち} else if (条件) {そのときの命令たち}` - `if (条件) {そのときの命令たち} else if (条件) {そのときの命令たち} else {そのときの命令たち}` - `else if` はいくつ書いても良いが、最初の `if` と最後の `else` はひとつだけ というような数パターンがあります(上で使ったのは2番目にあたります) `条件` には、 **条件式** というものを入れます その真偽の結果によって、実行する命令を変える仕組みです 上では、 `sum <= 1000` というのが条件式で、 これは `sum` に格納された値(総支出) が 1000 **以下** だったときだけ、 `if` の `{そのときの命令たち}` 部分に書かれた命令を実行してくれということです 対して、 `else` は **そうでないなら** です `else` より前に聞かれた条件がすべて偽の場合、最後にここを実行します 上の場合では `sum` に格納された値(総支出) が 1000 **以下でない**、つまり 1000 **より大きい** ときだけ、 `else` の `{そのときの命令たち}` 部分に書かれた命令が実行されることになります よってプログラムは以下のように書いてみます ```js let sum // 総支出を計算 sum = 134 * 2 + 584 + 266 // 総支出を表示 console.log(sum) // 条件分岐 if (sum <= 1000) { // 総支出が 1000 以下なら console.log('OK!') } else { // 総支出が 1000 以下でないなら console.log('NG...') } ``` これを実行すると、以下のように表示されます ``` 1118 NG... ``` 足りない……ということがよくわかるようになりました ちなみに買うものを減らして、134 円のクッキー 2つ、 584 円のチョコ 1つ だけを買うとすると、以下のように書けます ```js let sum // 買う品物を減らして、総支出を計算 sum = 134 * 2 + 584 // 総支出を表示 console.log(sum) // 条件分岐 if (sum <= 1000) { // 総支出が 1000 以下なら console.log('OK!') } else { // 総支出が 1000 以下でないなら console.log('NG...') } ``` これを実行すると、以下のように表示されます ``` 852 OK! ``` 今度は `sum` は `852` が格納されているので、 `sum <= 1000` が真となり、 足りる!ということがよくわかります #### お冷: 条件式の結果を見てみる 条件式の結果の真偽を見る仕組み、とは言ったものの、真偽とは……となると思うので、 実際にどんな結果が出ているのか見てみましょう 次のように、単に表示すればOKです `console.log(1 < 2)` この結果は次のように表示されます `true` `true` は真で、反対に `false` が偽です 次のように書くと ```js console.log(10 < 100) console.log(2.5 > 3) ``` この結果は次のように表示されます ``` true false ``` `<` や `>` などは **比較演算子** といい、数や文字列の比較をして、結果が出ます ちなみに 「等しいかどうか」を比較する演算子は `==` です - JavaScript はゆるいので、 `==` では驚くほどゆるい基準で「等しい」とされる場合があります - 厳密な「等しいかどうか」を比較する `===` という演算子があるので、それを使うほうが正確でしょう 余裕がある時に、条件式としてただの数値を入れたり、 `true` や `false` を入れたりしてみてください これ正しいのか……?とか、うまく動かないとかあれば聞いてください ## 5品目: 反復 最初に出てきた **プログラミングの三構造** について、すでに **順次** 、 **分岐** をやりました 最後に **反復** をします 例: 1 から 10 まで、それぞれの 3 乗を求めたい 順次な考え方だけで書くと、次のように書けます ```js // まず 1 の 3 乗 console.log(1 * 1 * 1) // 2 から順に 10 まで console.log(2 * 2 * 2) console.log(3 * 3 * 3) console.log(4 * 4 * 4) console.log(5 * 5 * 5) console.log(6 * 6 * 6) console.log(7 * 7 * 7) console.log(8 * 8 * 8) console.log(9 * 9 * 9) console.log(10 * 10 * 10) ``` これを実行すると次のように表示されます ``` 1 8 27 64 125 216 343 512 729 1000 ``` それぞれちゃんと計算できています(確認してみてください) ただ、これが 100 や 1000 などとなると、プログラムを書くのに膨大な時間がかかる上に、 ほとんど同じことを書くので、やっていられません これを反復(ループ)で賢くします JavaScriptには、代表的なループに `for` と `while` の 2 つがあります - `for` : **終わるまでの回数が決まっているとき** によく使われる - `while` : **終わるまでの回数がわからないとき** によく使われる - JavaScript のループは他にも沢山あります これらを使うと、同じ命令を何度も繰り返す、というのを賢く書くことができます 今は終わるまでの回数がわかっているので、 `for` を使ってみます `for` は - `for (初期化; 条件式; 毎ループ最後の命令) {繰り返す命令たち}` などと書きます(他にも書き方がありますが、とりあえず今は使いません) この形の `for` の流れは以下です 1. 最初に `初期化` を実行する 1. `条件式` を見て、真なら中の `繰り返す命令たち` を実行する (偽なら `for` 全体を飛ばす) 1. 中の `繰り返す命令たち` の実行が終わったら、 `毎ループ最後の命令` を実行する 1. `条件式` を見て、真なら中の `繰り返す命令たち` を実行する (偽なら `for` 全体を飛ばす) 1. 中の `繰り返す命令たち` の実行が終わったら、 `毎ループ最後の命令` を実行する 1. `条件式` を見て、真なら中の `繰り返す命令たち` を実行する (偽なら `for` 全体を飛ばす) 1. 中の `繰り返す命令たち` の実行が終わったら、 `毎ループ最後の命令` を実行する 1. `条件式` を見て、真なら中の `繰り返す命令たち` を実行する (偽なら `for` 全体を飛ばす) ...と続きます `for` でよくある使い方として、 **カウンタ** と呼ぶ変数をひとつ使って、ループを繰り返した回数を数えながら、 決めた回数に到達したら終了する、というものがあります カウンタはよく `i` を使う慣習がありますが、なんでもOKです これを使って以下のように書きます ```js // カウンタ i の宣言 let i for (i = 1; i <= 10; i = i + 1) { // ここが 10 回繰り返される console.log(i * i * i) } ``` 劇的に短くなりました `i` の値をループが終わるごとにひとつずつ大きくしているので、 ループが回るごとに 1~10 の 3 乗が順に計算されるはずです これを実行すると次のように表示されます ``` 1 8 27 64 125 216 343 512 729 1000 ``` 正しく計算されました 11 の 3 乗が計算されずにちゃんと終了しているのは、 - `i` が 10 のときのループが終わったあとに `i` がひとつ増やされ 11 になる - `i <= 10` の結果を出すと偽となり、 `for` 全体を飛ばす ということが起きているからです #### お冷: 例題 同じように `for` を使って、 「10 から 23 まで、それぞれの 2 乗から 300 を引き算する」をしてみます ```js let i for (i = 10; i <= 23; i = i + 1) { console.log(i * i - 300) } ``` 実行すると次のように表示されます ``` -200 -179 -156 -131 -104 -75 -44 -11 24 61 100 141 184 229 ``` ## 6品目: FizzBuzz問題 所謂「FizzBuzz問題」をやってみましょう ~~~ 1 から 100 まで、数を表示する ただし、次の条件に従う: - 数が **3 で割り切れるとき** 、 数ではなく、『Fizz』と表示する - 数が **5 で割り切れるとき** 、 数ではなく、『Buzz』と表示する - 数が **3 と 5 両方で割り切れるとき** (つまり15で割り切れるとき) 、 数ではなく、『FizzBuzz』と表示する ~~~ 割り切れるかどうかを確認するためには、余りが存在するかどうかを見ると早いです 自分で余りを求めるプログラムを書いてもOKですが、剰余演算子( `%` )という演算子を使うとすぐです `4 % 2` の結果は `0` `5 % 2` の結果は `1` `100 % 32` の結果は `4` _どのくらい時間があるかわかりませんが、_ 自分で / 教えてもらいながら / 教えながら書いてみてください 答えは以下に示します [FizzBuzz問題の解答例](https://wiki.mma.club.uec.ac.jp/hogas/ProgrammingSeminar2017/fizzbuzz) ## デザート: 結び 沢山やったような気もしますが、実はプログラミングのほんの触りだけだったりします 基礎の基礎の導入、という事項を扱いましたが、 これ以上の内容は(ひとつの言語でも)とても沢山存在するので、是非学んでみてください #### 参考 - [JavaScript リファレンス - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference) - [airbnb/javascript: JavaScript Style Guide](https://github.com/airbnb/javascript) - [Javascript-style-guide](https://mitsuruog.github.io/javascript-style-guide/)