上杉周作

「プログラミング」と「プログラミング的思考」の違いを、分かったつもりになれるヒント

学校の先生方へ

前回の記事では、文科省が行った小学生向けプログラミング教育の有識者会議について、記事をいくつか取り上げました。その中のひとつを再度引用します。

13日の会合では委員から「プログラミング言語そのものでなく、コンピューター的な考え方を教えるべきだ」(中略)などの意見が出た。(朝日新聞 / 2016年5月13日)

この「コンピューター的な考え方」とはいったい何なのでしょうか? また、なぜそれがプログラミング言語を学ぶことより重要なのでしょうか? 今回はこれらの疑問にぼくなりに答えていきたいと思います。

まず、有識者会議の議論取りまとめを見てみましょう

2016年6月16日に公開された議事録「小学校段階におけるプログラミング教育の在り方について」より、さきほどの問いと関連する部分を、やや冗長になりますが抜粋していきます。

冒頭のまとめ部分より:

小学校段階におけるプログラミング教育については、学校と民間が連携した意欲的な取組が広がりつつある一方で、コーディング(プログラミング言語を用いた記述方法)を覚えることがプログラミング教育の目的であるとの誤解が広がりつつあるのではないかとの指摘もある。

“小さいうちにコーディングを覚えさせないと子供が将来苦労するのではないか”といった保護者の心理からの過熱ぶりや、反対に“コーディングは時代によって変わるから、プログラミング教育に時間をかけることは全くの無駄ではないか”といった反応も、こうした誤解に基づくものではないかと考えられる。

プログラミング教育とは、子供たちに、コンピュータに意図した処理を行うよう指示することができるということを体験させながら、将来どのような職業に就くとしても、時代を超えて普遍的に求められる力としての「プログラミング的思考」などを育むことであり、コーディングを覚えることが目的ではない。

どうやら、「コンピューター的な考え方」は「プログラミング的思考」と呼ぶそうです。では、そのプログラミング的思考とは何なのか:

子供たちが、情報技術を効果的に活用しながら、論理的・創造的に思考し課題を発見・解決していくためには、コンピュータの働きを理解しながら、それが自らの問題解決にどのように活用できるかをイメージし、意図する処理がどのようにすればコンピュータに伝えられるか、さらに、コンピュータを介してどのように現実世界に働きかけることができるのかを考えることが重要になる。

そのためには、自分が意図する一連の活動を実現するために、どのような動きの組合せが必要であり、一つ一つの動きに対応した記号を、どのように組み合わせたらいいのか、記号の組合せをどのように改善していけば、より意図した活動に近づくのか、といったことを論理的に考えていく力が必要になる。

こうした「プログラミング的思考」は、急速な技術革新の中でプログラミングや情報技術の在り方がどのように変化していっても、普遍的に求められる力であると考えられる。

「抽象的すぎて何がなんだか」と思われたかもしれません。ぼくもです。この記事の本題では、できるだけ抽象的な表現は使わないように心がけますので、ご安心ください。

有識者会議ではさらに、「コーディングやプログラミング言語と違い、プログラミング的思考は普遍的であるから、教えたことが無駄にはならない」とも論じられています。

特定の技術や個別のプログラミング言語については、時代の変化や技術革新の中で移り変わっていくことが予測される。ここ十~数十年の間において、プログラミング言語が果たす役割が大きく変わるわけではないが、将来的には、私たちが日常的に用いる自然言語で論理的に書いたり話したりすることで、コンピュータに指示できるようになるのではないか、との予測もある。

仮にそのような時代になったとしても、社会でコンピュータが果たす役割を理解しながら、「プログラミング的思考」を発揮し、その時代の情報技術を効果的に活用して問題を発見・解決していくことの重要性は変わらないものと考えられる。

(中略) プログラミング教育の実施に当たっては、コーディングを覚えることが目的ではないことを明確に共有していくことが不可欠である。

文科省の資料からは以上ですが、冒頭の、

  • 「コンピューター的な考え方」とはいったい何か?
  • また、なぜそれがプログラミング言語を学ぶことより重要なのか?

という質問にたいする具体的な答えはありませんでした。というわけで、プログラミング未経験の方にたいしてもなるべくわかりやすく、ぼくなりに説明させていただきます。

数学パズル

はじめに、とある数学のパズルを紹介します。数学に詳しい方はご存知かもしれません。難しい数式は出てこないのでご安心を。

ここに、4×4のマス目があります。

16あるマスのうち、どこか2つにバツをつけます。ためしにこの2箇所につけてみます。

次に、残りの14マスに線を引いていきます。ひとつの線は、(1)タテかヨコに並んだ2つのマスに引けますが、(2)同じマスにふたつの線があってはいけません。また、(3)バツには線を引けません。

つまり、下のような線の引き方はOKということです。

これを繰り返せば、最終的にバツを除いた全てのマスに線を引くことができます。

では、ここで問題です。今度はバツを違う位置につけてみました。同じように、14マスすべてに線を引いてみてください。

ためしにやってみると、右下の2マスが余ってしまいますね。

もう一度やってみても、こんどは左の2マスが余ってしまいます。

じつはこの14マスだと、ぜったいに全てのマスに線を引けないようになっているのです。ここで問題なのですが、そうなるのはなぜでしょうか?

紙とペンがあれば、すこし考えてみてください。

答えを言う前に

この問題は数学者には「ドミノタイリング問題」の一種として知られています (線の代わりに、2×1マスのドミノを使うからです)。

ちなみに、もしバツをひとつもつけない場合、線の引き方が何通りあるかは1961年に計算されました。公式は複雑なので載せませんが、バツ無しの4×4だと36通り、6×6だと6728通りあり、バツをつければいくらか引き方は減るはずです。

これくらいの数でしたら、さきほどの「全てのマスに線を引けるか」問題もプログラミングで解決できそうです。「しらみつぶし」にすべての線の引き方をためすプログラムを書き、どれも無理だったら、「できない」と出力すればいいのです。

しかし、8×8マスだと1300万通りの引き方があり、

10×10マスだと約2600億通り、12×12マスだと約5京(兆の次の単位)通りあります。いくらコンピューターが速いとはいえ、10×10マス以上で「全てのマスに線を引けるか」問題をプログラミングで「しらみつぶし」に解こうとすると、スパコンのような超高速コンピューターが必要になってくるでしょう。

さきほどの問題の答え

話を戻すと、なぜこの14マスだと全てのマスに線を引けないのでしょうか。答えを説明させていただきます。

まず、チェスボードのように、白のマスと青のマスに塗りつぶしていきます。

この状態でもう一度線を引こうとします。やはり2マス余りますね。

では質問なのですが、余ったマスは何色でしょうか? 2マスとも白ですね。さきほど失敗した例でも、余ったのはどちらも白のマスでした。

ここで、線とマスの色に注目してみてください。ひとつの線は必ず、青1マスと白1マスに引かれますね

では、バツを除くと、この14マスのうち青は何マス、白は何マスでしょうか?

青6マス、白8マスですね。もうお分かりでしょうか。ひとつの線は必ず青1マスと白1マスに引かれるので、白マスのほうが青マスより2つ多いため、どんなにがんばっても最後に白マスが2個残ってしまうのです。

つまり、答えは「チェスボードのように全てのマスを青と白に塗りつぶして、バツを引いたあとに青と白の数が一致していなかったら、全てのマスに線を引くのは不可能である」ということでした。

プログラミングに話を戻すと

さきほど、「10x10マス以上で全てのマスに線を引けるか」を、「しらみつぶしに試す」プログラムを書いて解こうとした場合、コンピューターにかなりの処理速度が必要になると話しました。10×10マスでもバツが無ければ約2600億通りも引き方がありますしね。

いっぽうで、「チェスボードのように全てのマスを青と白に塗りつぶして、バツを引いたあとに青と白の数が一致するか」を確かめるプログラムはどうでしょう。

10x10マスでも全部で100マスしかないので、すぐ処理が終了しそうですよね。もちろん、青と白の数が一致していても全てのマスに線を引くのが不可能な場合も稀にありますが、多くの不可能なケースはこのプログラムで判別できそうです。

つまり、一見プログラミングで解こうとすると骨が折れそうな問題でも、問題の見方を変えれば(この問題だと、青と白で塗りつぶすこと)、プログラミングで簡単に解ける問題になるのです

プログラミング的思考に話を戻すと

ぼくはカーネギーメロン大学という、世界的にもコンピューターサイエンスが有名な大学でコンピューターサイエンスを専攻しました。そして先ほどの「線引き」問題は実は、コンピューターサイエンス専攻生全員が一年生で受講する「コンピューターサイエンスのための数学」の授業で最初に出された問題だったのです。この問題を出したあと、教授はこう言いました。

君たちはこれから大学四年間でプログラミングを学ぶが、プログラミングを学ぶだけでは、この「線引き」問題でも見せたように不十分だ。

コンピューターが人間の役に立つためには、人間はコンピューターに「この問題を解いてくれ」という命令を出す前に、その問題の正しい見方をしないといけない。「線引き」問題の場合、正しい見方とは「青と白に塗りつぶす」ことだ。

コンピューターが問題を解きやすいように、問題の正しい見方をすること」を、コンピュテーショナル・シンキング(計算論的思考)と呼ぶ。

これは我が大学のジャネット・ウイング(元カーネギーメロン大コンピューターサイエンス学部長、現マイクロソフトリサーチ副社長)が提唱した概念だ。きみたちにはこれから4年間、みっちりコンピュテーショナル・シンキングを学んでもらう。

この「コンピュテーショナル・シンキング」は文科省の用語「プログラミング的思考」と置き換えて問題ありません。よって、プログラミング的思考とは、コンピューターが問題を解きやすいように、問題の正しい見方をすることだと言えます

(追記: 有識者会議の資料には、「プログラミング的思考とは、いわゆる『コンピュテーショナル・シンキング』の考え方を踏まえつつ、プログラミングと論理的思考との関係を整理しながら提言された定義である」と、ふたつの概念は微妙に違うように書かれていますが、定義を必要以上に複雑にしているだけなので、無視して構わないと思います。)

コンピューターが問題を解きやすいように、人間が知恵を絞ること

プログラミング的思考、すなわち「コンピューターが問題を解きやすいように、問題の正しい見方をすること」とは突き詰めて考えれば、「コンピューターが問題を解きやすいように、人間が知恵を絞ること」だといえます。

そして、その知恵の集大成がコンピューターサイエンスであるとぼくは思っています。医療についての人間の知恵の集大成が医学であるように。

さきほどの「線引き」問題の例を出すとよく、「プログラミング的思考とは数学なのか」と思われます。しかし、「コンピューターが問題を解きやすいように、人間が知恵を絞ること」は数学だけにとどまりません。

たとえば、スマホのアプリなどを使いやすくするため、「ユーザー体験をデザイン(UXデザイン)する」ことがIT業界では流行っていますが、それの大本は「HCI (ヒューマン・コンピューター・インタラクション)」という学問分野です。教育になぞらえるなら、学校での指導が「UXデザイン」で、教育学が「HCI」になります。

HCIは「どうやったらコンピューターが人間にとって使いやすく進化できるか?」「人間とコンピューターとの新しい接し方はないか?」など「コンピューターと人間の接点」を研究する学問です。HCIの学者がいなかったら、スマホも生まれてなかったかもしれません。(ちなみに、ぼくはカーネギーメロンの大学院でHCIを勉強しました。)

HCIも「コンピューターが、『どう人間と上手くやっていくか』という問題を解きやすいように、人間が絞った知恵」であるゆえに「コンピューターサイエンス」「プログラミング的思考」の一部ですが、HCIは数学よりも心理学とデザインの影響を受けています。だから、プログラミング的思考は数学だけではありません。

プログラミング的思考は、人間への課題

最後に恐れながら、自分の意見を一つだけ言わせてください。

プログラミングに詳しくない先生たちのあいだで、「プログラミング的思考」という言葉が一人歩きすることによってぼくが恐れているのは、教育現場などでコンピューターのことにばかりスポットライトが当てられてしまうことです。

有識者会議でも同じような意見が出ていましたが、プログラミング的思考の本質が「コンピューターが問題を解きやすいように、人間が知恵を絞ること」なのだとしたら、教育現場ではコンピューターと同じくらい、人間にスポットライトが当てられるべきです

例をあげます。マサチューセッツ工科大学(MIT)が出版し、MITをはじめ多くの大学のプログラミング入門講義で使われた「計算機プログラムの構造と解釈」という古典的な教科書があるのですが(上の画像)、この本の冒頭に、多くのプログラマに語り継がれる名言が残されています。

プログラムは、人々がそれを読むために書かれるべきである。 たまたま、それが計算機で実行できるにすぎない。(引用元)

ぼくはプログラミングを勉強する前は、「コードはコンピューターに命令をするためにある」と思っていました。たしかにそうなのですが、いざプログラマになってみると、「コードは人が読むためにある」と思う比重のほうが大きくなったのです。

なぜなら、ほとんどのソフトウェアは大人数で開発するため、自分が書いたコードを他人が理解できなかったり、他人が書いたコードを自分が理解できなかったりすると、開発が滞るからです。

「コードは人が読むためにある」ということは、プログラマには「常識中の常識」なので書くのもはばかれるのですが、プログラミング未経験の方にとっては初耳だったのではないでしょうか。

さらに補足すると、前回の記事ではプログラミング言語「Ruby」開発者・まつもとゆきひろ氏のプログラミング教育についての発言を引用しましたが、当初Rubyの人気が出た理由のひとつは、「Rubyのコードは他人が読んでも理解しやすいから」でした。

何が言いたいかというと、「コード」という、プログラミングにおいて最も重要なものでさえ、人間にスポットライトが当たるものなのです。

プログラミング的思考は、人間の知恵であり、人間への課題です。このことを踏まえた上で、子ども向けのカリキュラムを作っていきたいものですね。

今回はこのへんで。長い記事にお付き合いいただきありがとうございました。

追記

AERA2016年10月31日号に当記事の問題が掲載されました。また、さらに新しく2つの問題を書きました。

月曜に発売された雑誌AERAの最新号は「プログラミング思考」についてなのですが、3ページほどお借りして、プログラミング思考に関連するクイズを書かせていただきました。...

Posted by Shu Uesugi on Monday, October 24, 2016