【質問#141】独学でコンピュータサイエンスはどのように学べますか?

質問・悩み相談の回答です。

質問

高校3年生です。前々からプログラミングというものに憧れがあります。それはプログラマーが賢そうで、自分もプログラミングの世界を知り賢くなりたいからということがあります。ただ憧れ以外にも学びたい理由があります。自分は、ほぼ全くプログラムやコンピュータサイエンスの世界に関して知らないのですが、その事実がよりその世界を知りたいと思わせています。自分の身の回りにはそういった世界をもってして?(本当に何も知らないので推測も混じりますが)作られたpcやスマホ、インターネットやゲームがあり、それらをただ何も知らずに使って生きている、そういう現実が気持ち悪いと思うのです。将来子供を持てば、その世代にはもっと技術が進んでいて今始めなければもう完全に追いつけないような気がします。また、家族や親戚にも詳しい人がいませんが普通に使っていて、セキュリティとかも大丈夫なのか不安になります。そこで、自分がそういう世界に足を踏み入れ、色々知ることができれば問題なく、そして安心して自分や家族がpcやスマホを使えるようになるのでは、と思いました。

(最後のセキュリティに関しては、ネットで調べればわかるのかもしれませんが、どのように調べれば安心した情報が得られるのかわかりませんし、そうして結果だけ知るよりも自分で学んで知ってみたいです。)
ここからが本題なのですが、全く何も知らない自分のような人が独学でコンピュータサイエンスやプログラミングの世界に足を踏み入れようと思った時どのような分野や内容から入ればいいのでしょうか。また、全体像が見えないので、学校の情報の授業であるプログラミング言語を少し習ったのですが、それらが普段自分が眼にしているゲームやアプリ、サイト、他にも目にしていないようなセキュリティのソフトや知らない何かにどうつながっていくのかがわからず、何を勉強すればどういったことを目指せるのかもわかりません。

大学では生物系に進もうと思っており、又実家を継ぐつもりで、IT系の会社に就職しようと考えているわけでもありませんので、単純に趣味のように学ぶことになるかもしれないのですが、とにかくどんな世界なのか、自分にとっては学問分野の1つのように見えているのですが、系統立てて教えて貰いたいです。あと、副業的にできることがあるならそれについても知りたいです。
長文で分かりにくい文だったと思いますが、回答していただければ嬉しいです。

回答

すばらしい!ぜひ勉強してみてください。生物系に進むとしても、実家を継ぐとしても、コンピュータは必ず使うので勉強しておいて損は無いです。

自分は、ほぼ全くプログラムやコンピュータサイエンスの世界に関して知らないのですが、その事実がよりその世界を知りたいと思わせています。
自分の身の回りにはそういった世界をもってして?(本当に何も知らないので推測も混じりますが)作られたpcやスマホ、インターネットやゲームがあり、それらをただ何も知らずに使って生きている、そういう現実が気持ち悪いと思うのです。

近年の電子機器はどんどん小型化・ブラックボックス化・複雑化が進んで素人が手出しできなくなってきていますからね…。そんな中、スマホやPCを漫然と使うのではなくて仕組みを知ろうとおもう興味は非常に大事だと思います。コンピュータに限らず、物事や社会の仕組み、構造がどうなっているかについて疑問を持ち、調べるというのは成長していくために非常に大事なスキルです。

現実世界のいろんなことに疑問や興味を持つというのはとても重要なことなのですが、意外と義務教育や高校大学でもそれを養う教育ってされてないんですよね。幼稚園や保育園ではそういうことはよくされているっぽいのですが、小中高になると「何とか見学」「何とか体験」みたいなのを申し訳程度にやる程度で、あんまり意味が無いように思います。

単純に趣味のように学ぶことになるかもしれないのですが、とにかくどんな世界なのか、自分にとっては学問分野の1つのように見えているのですが、系統立てて教えて貰いたいです。

承知しました。ちなみにコンピュータサイエンス(日本語では計算機科学)は立派な学問分野の一つで、コンピュータが開発される以前から続いている分野です。

というわけで、私が良いとおもう勉強法、書籍、方法などを挙げてみますので、興味を持てるものから取り組んでいただけたらと思います。「興味をもてるものから」というのが重要です。興味のないところを調べていってもモチベーションが続かず飽きて終わるので。

Wikipedia

Wikipediaはよくソースとして不適切とか正確じゃないとか言われてますが、まず最初の導入としては手軽ですし悪くないと思います。書いている内容は基本、間違いがどこかに含まれていると思いつつ読んでいけばよいでしょう。

計算機科学の項を読み、適当にリンクを辿っていって興味の持てそうなところを読んでいってください。興味が沸くところがあったらキーワードだけ覚えておいて、そのキーワードで検索した書籍をAmazonで探し、古本とかKindleとかで読んでみると良いと思います。

ちなみに私が好きなのは以下あたりです。が、最初にいきなり読んでも意味がわからないかもしれませんが…。雰囲気だけでも感じ取っていただけたらと。

オートマトン
チューリングマシン
そもそも、コンピュータとは日本語でいうと「計算機」です。パソコンもスマホも基本的には計算機です。音楽を流したり動画を再生したりネットを閲覧したりするのも、実は電卓で叩いて計算するのと同じようなことを内部でやってます。計算機なので解いているのは数学の問題です。プログラマというのは、実は世の中のあらゆる問題を数学の問題にして計算機に解かせる作業を行っている人たちです(そういう認識のないプログラマもたくさんいるとおもいますが、そうなんです)。

では、その計算機とは一体どういう定義なのか?何をするものが計算機なのか?現代のコンピュータを究極的に単純化すると、つまり何をやっているのか?というのがオートマトンやチューリングマシンを勉強するとわかってくると思います。

計算可能性理論
その計算機を使ってどんな問題が解けるのか?どういう問題が解けないのか?を語る分野が計算可能性です。有名なところでは、上記のページにも書いている「チューリングマシンの停止性問題」というのがあります。現代のコンピュータは(そしておそらく現代のコンピュータの形から発展していく将来のコンピュータでさえ)、「あるプログラムを実行したら無限ループになるのか、それとも停止するのか」を判定することができません。つまり、これから解こうとしている問題に終わりがあるのか、無いのかを判定することはできないということです。

ちなみに計算可能性理論とはちょっと違いますが、コンピュータはそれ自身で「ランダムに何かを決める」ということができません。プログラムで「こうしろ」と言われたことしかできないからです。A、B、Cという手順を繰り返せと言われたらそうしかできないのです。

いや、ゲームでランダムに出てくる敵とか居るじゃん、乱数使ってるじゃんと言われるかもしれませんが、あれは擬似乱数というもので乱数に見えるけれども実は手続き的に導き出した数字で、やり方を知っていれば常に同じ数字が出てきます。だからゲームでTASプレイとかできるわけですね。もうすこし予想しにくい乱数を使う場合は、現代のコンピュータではキーボードやマウスの入力とかネットワークとかのアクセスをもとに「エントロピープール」というのを溜め込んで、そこから乱数を生成します。

本当の乱数が必要な場合は仕方ないので、放射線同位体を含んだチップを内蔵し、それの放射線を検知して乱数を作るなどします。そこまでしないと乱数って作れないんですね。

計算複雑性理論

計算複雑性とは、コンピュータで解こうとしている問題がどのくらい難しいのか?について語る分野です。

簡単な問題の例としては、たとえば 10 * 4 = ? みたいな問題です。人間でも暗算で解けますね。

もう少し難しい問題としては、「ばらばらになったN個の単語を辞書順に並べる(ソートする)」とかです。ソートはアルゴリズムの基礎でよく出てくる例で、朝のEテレのピタゴラスイッチでも「しめじソート」とかいうのが出てくるのでご存知でなければぜひ見てみてください。YouTubeで検索すると、しめじソートを紹介してる動画がいくつかヒットします。

人間が「ばらばらになったN個の単語を辞書順に並べる(ソートする)」なら、おそらくはまず一番先頭にくる単語を探し、それが終わったら二番目にくる単語を探し…という方式で並べ替えていくと思います。これは選択ソートと呼ばれる方法で、難しい言葉でいうと O(n^2) の計算量であるといいます。これはソートの方法の中では性能の悪い方法です。

しめじソートは正確にはマージソートと呼ばれる方法で、これは O(nlogn) の計算量で、ソートアルゴリズムの中では良い性能です。

ソートの難しさはPと呼ばれるクラスに分類されます。Pよりも難しい(と思われている)クラスにNPというのがあり、例を挙げると巡回セールスマン問題というのがあります。これは、セールスマンの訪問先がいくつか与えられたときに、どのような順序で訪問先を辿っていけば移動距離が最小になるか?という問題です。これは今の所ソートよりは難しいと考えられています。

その他のNPの問題としては、「ぷよぷよの盤面と次にくるぷよぷよが与えられたときにN連鎖可能か否か」を判定するという面白い問題なんかもあります。今の高校3年生はぷよぷよ知らないかもしれないけど…。

ちなみにこれはP≠NP予想と呼ばれている未解決問題で、「巡回セールスマン問題はソートと同じ時間では解けない」あるいは「巡回セールスマンはソートと同じ時間で解ける」ということが証明できればクレイ数学研究所から100万ドルがもらえるのでチャレンジしてみてはいかがでしょうか。

大学の講義資料

ありがたいことに、計算機科学の分野では大学で使用している講義資料がネット上で一般的に公開されているものが多いです。Wikipediaで面白そうなキーワードを見つけたらググってみましょう。資料が山ほどPDFで見つかります。これらの講義資料はWikipediaよりも正確で、かつ学生に理解させるために書いたものなのでよりわかりやすいと思います。

ちなみに今ググってみて「なんかこれ見たことあるな…」というものが出てきたのですが、よく見たら私の恩師が書いた資料でした。

書籍

私は全部大学で、各種教科書で勉強してました。なのであまり一般向けで良い書籍というのは知らないのですが、しかし下記の「~がなぜ~なのか」シリーズはとても良いと思っています。そのタイトルの通り、なぜそれらがうまく動作するのかが、一般の人でも分かるように書かれています。多少専門的になってしまうところがあるのは仕方ないですが…。

古くからある本で、古本で安く手に入るのも学生にはありがたいですね。

コンピュータはなぜ動くのか~知っておきたいハードウエア&ソフトウエアの基礎知識~
矢沢 久雄 日経ソフトウエア
日経BP社
売り上げランキング: 12,408
プログラムはなぜ動くのか 第2版 知っておきたいプログラムの基礎知識
矢沢久雄
日経ソフトウエア
売り上げランキング: 4,215
携帯電話はなぜつながるのか 第2版
中嶋信生 有田武美 樋口健一
日経BP社
売り上げランキング: 216,844

その他、Amazonで適当に探しましたが、あんまり良さそうなのが無かったです。

数学が嫌いでなければ、下記も良さそうかな?と思いました。

みんなのコンピュータサイエンス
Wladston Ferreira Filho
翔泳社
売り上げランキング: 8,281

一般向けのわかりやすくて楽しい計算機科学の本ってあまりないので、noteとかで書いてみようかな…。

Linuxを使う

Linuxを使うとコンピュータ技術のことがよくわかります。特にセキュリティに関してはLinuxを日常的に使っていると知識が深まります。なぜならば、各種Webサービスやネットワーク機器の多くはLinuxで動いていますから、Linuxが使えればそれらがどういう仕組で動いていて、何ができるのかがわかります。仕組みとできることがわかったら、それをクラックする方法も理解できます。クラックする方法がわかれば、防衛策も分かるということです。

Linuxを勉強する際は、今だと仮想マシンやWSL(Windows Subsystem for Linux)という仕組みもあり、PCを使いつつLinuxも使えるという手軽さな方法もありますが、個人的には一台、中古のノートパソコンを買ってきてUbuntu(Linuxの一つ)を入れてそれだけを使ってみる、ということをしてみると良いと思います。強制的にLinuxしか使えない環境に身を置けば、Linuxでのやり方がどんどん理解できます。

特にセキュリティに興味があるのであれば、Kali Linuxというハッキングツールがたくさん入ったものがあるので、それをインストールした上で自分で作ったサーバをクラッキングしたり、コンピュータウィルスまがいのものを作って自分の環境に感染させてみたりしてスーパーハッカーごっこをして遊ぶのも良いでしょう(神奈川県警・兵庫県警さん、捕まえないでね)。

Raspberry Piを使う

Raspberry Piというおもちゃがあります。

これは手のひらサイズのコンピュータで、4000円くらいで買えます!4000円ですよ!?すごくないですか?このページ読んでる人で買ってない人がいたら今すぐ買いましょう。買うときはAmazonとかだと高く出品されているので上記RSオンラインで購入しましょう。

4000円のコンピュータですが、ディスプレイとキーボードを繋いで起動すれば普通のPCとまったく同じように使えます。性能的にちょっと非力なので、予算に都合がつくならほかの高性能ボードを買っても良いでしょう。

内部でLinuxが動作しており、かつGPIOピンが付いているのでいろんなことができます。

以前は帰省中に子供が学校から持って帰ってきたアサガオを枯らさないために自動水やりシステムを作ったりしました。スマホからログインしてカメラで様子を見つつ、リモートで水をあげることができます。アイディアさえあればこんな感じのものもすぐできてしまいます。

もし工作がお好きで興味が持てそうであれば、こういう方面から入っていっても良いかもしれないですね。

というわけで、色々思いつくものを挙げてみました。繰り返しになりますが、何よりもまず「興味を持てること」「楽しいと思えること」を優先して気になるところから取り組んでいくのが良いと思います。何か面白そうなところを見つけて、そこを掘り下げていって知識を広げていってみてはいかがでしょうか。