2014年12月14日日曜日

Hour of Code

このサイトは移転しました。1秒後に自動でジャンプします。
移動しない場合は、ここをクリックしてください。



最近、Hour of Codeというサイトを知りました。

息子にプログラミングを教えたいと言いながら、コンピュータ教育の動向をあまり把握できて恥ずかしいかぎりですが、Scratchやblocklyのような制御ブロックを使って楽しみながらプログラミングの基礎が学べる素晴らしいサイトです。

『アナと雪の女王』を使ったコンテンツ、自分も思わず遊んでしまいました。これが『妖怪ウォッチ』ならば、息子もすぐに飛びつくかもしれないですね。



次の世代の子供達をどのように育てていくかということが、自分がこれから取り組んでいきたいテーマです。本サイト『息子に教えるJavaScript』は、そのうち、コンピュータをどうやって教えていくかということを模索する目的で執筆をはじめました。

息子に教えることを通じて、これからを担っていく子供達にコンピュータを教えていきたいというのが自分が目指しているところですので、今後、こういった素晴らしいコンテンツがあれば取り上げていきたいと考えています。

2014年12月13日土曜日

JavaScriptの可能性

このサイトは移転しました。1秒後に自動でジャンプします。
移動しない場合は、ここをクリックしてください。



JavaScriptが生まれた当初、自分は、フォームに入力した値のチェックや、HTMLを動的に変更してボタン有効/無効を制御したり、Webページに動きを与えるスクリプトという程度の認識しかありませんでした。Webブラウザ上で凝ったことをするにはJavaScriptでは不十分で、JavaアプレットやFlashを使う必要がありました。

この認識が大きく変わったのは、『Ajax』と呼ばれるサーバとの非同期通信を活用したWebページの登場や、一部ブラウザが『Canvas』と呼ばれる描画オブジェクトを独自にサポートしはじめたことでした。

JavaScriptの新しい活用方法が見出された結果、jQueryなどの便利なライブラリが生まれました。そして、これらの高機能化に対応すべくJavaScriptの処理エンジンの高速化が図られました。
スマートフォンやタブレットの登場も手伝って、カメラやオーディオの制御などもJavaScriptから行えるようになってきたことも大きな進化といえるでしょう。

HTMLがWebページを記述するための言語として揺るぎない地位を確立したのと同様に、JavaScriptも『ECMAScript』という規格で標準化が進められ、Webブラウザなどのフロントエンドで使われる言語として、今後ますます利用されていくでしょう。

Webブラウザ一つあればプログラム開発から実行まで行えるという手軽さは、プログラミングの教育にも適しており、今後、JavaScriptを学ぶ学生もたくさんいるでしょう。

そして、JavaScriptのもう一つ見逃せない動きがNode.jsの誕生です。
Google社が開発した『Chrome』ブラウザのJavaScriptエンジンを使って、サーバ上でJavaScriptを実行するという進化は、もはやJavaScriptがフロントエンドにとどまらないことを示しています。

2014年12月9日火曜日

Lesson18: 2のべき乗

このサイトは移転しました。1秒後に自動でジャンプします。
移動しない場合は、ここをクリックしてください。



同じ数値を足し合わせて得られた値を2つ足し合わせて、どこまでいけるか計算してみたよとノートを見せてくれた息子。
1 + 1 = 2
2 + 2 = 4
4 + 4 = 8
  ・
  ・
  ・
これは2進数の各桁なんだよと教えてしまいたくなるけど、まだ早いと思うので教えるのは今度にして、今回はコンピュータを使って同じ計算を行うサンプルをつくってみた。

はじめは何だかよく分からなくても、繰り返し続けていくうちにきっと何かひらめくときがくるはず。
そのときが訪れることを願って、これからも短いサンプルを書いて、
息子に教えていきたいと思う。

https://github.com/toshio/js4son/blob/master/chapter02/lesson18.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Lesson18 Binaries</title>
  </head>
  <body>
    <div id="text"></div>
    <script>
    var value = "<table border='0'>";
    for (var i=0, a=1; i<=50; i++) {
        value += "<tr>"
               + "<td>2<sup>" + i + "</sup></td>"
               + "<td>=</td>"
               + "<td align='right'>" + a + "</td>"
               + "</tr>";
        a *= 2;
    }
    value += "</table>";
    document.getElementById("text").innerHTML = value;
    </script>
  </body>
</html>

実行結果

20=1
21=2
22=4
23=8
24=16
25=32
26=64
27=128
28=256
29=512
210=1024
211=2048
212=4096
213=8192
214=16384
215=32768
216=65536
217=131072
218=262144
219=524288
220=1048576
221=2097152
222=4194304
223=8388608
224=16777216
225=33554432
226=67108864
227=134217728
228=268435456
229=536870912
230=1073741824
231=2147483648
232=4294967296
233=8589934592
234=17179869184
235=34359738368
236=68719476736
237=137438953472
238=274877906944
239=549755813888
240=1099511627776
241=2199023255552
242=4398046511104
243=8796093022208
244=17592186044416
245=35184372088832
246=70368744177664
247=140737488355328
248=281474976710656
249=562949953421312
250=1125899906842624

2014年12月4日木曜日

Lesson17: アルゴリズム(素因数分解)

このサイトは移転しました。1秒後に自動でジャンプします。
移動しない場合は、ここをクリックしてください。



車の仕組みが分からなくても車の運転ができるように、コンピュータの仕組みがわからなくても、豊富なアプリケーションを使いこなして、たいていのやりたいことはできると思います。

それでもなお、息子にコンピュータの仕組みやプログラミングについて学んでほしいと考えているのは、プログラミングを通じて、考える力を身につけてほしいと考えるからです。

例えば、ある数値の素因数分解を行うとき、素数の順に割れるかどうかを見て素因数を求めていきます。このように、問題を解く手順のことをアルゴリズムと呼び、プログラミングとは、そのアルゴリズムを記述することにほかなりません。

プログラムを書いてしまえば、面倒くさい計算はコンピュータが実行してくれます。
小さい頃は四則演算などを一生懸命練習して計算力を身につけることはとても重要なのですが、それなりに計算ができるようになったら、どのようにすれば解けるのかというアルゴリズムを考えてカタチにする力をつけていってほしいと思います。

今回は、素因数分解を行うJavaScriptを書いてみました。
まだ素因数分解を習っていない? そんなルールに縛られることなく、知っていることを教えていきたいと思います。
今はまだよく理解できなかったとしても、いつかそうした断片的な知識がつながる瞬間がくると確信しています。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Lesson17 Prime factorization</title>
  <body>
    <input id="number" type="number" min="2" max="10000" placeholder="Number" onchange="answer();"/>
    <input id="result" type="text"   maxlength="40" placeholder="result" readonly="readonly" />
    <script>
    function answer() {
        var number  = parseInt(document.getElementById("number").value);
        var value   = "";
        if (number) {
            value = factorize(number).join(" × ");
        }
        document.getElementById("result").value = value;
    }

    function factorize(value) {
        var factors = [];
        var divisor = 2;
        while (value >= 2) {
            if (value % divisor == 0) {
                value /= divisor;
                factors.push(divisor);
            } else {
                divisor++;
            }
        }
        return factors;
    }
    </script>
  </body>
</html>

素因数分解は、素数で割っていくことが基本ですので、そもそも2以外の偶数で割る必要がないなどを考慮すれば、もっと計算量の少ないアルゴリズムがかけると思います。

2014年12月3日水曜日

Lesson16: Canvas (時計)

このサイトは移転しました。1秒後に自動でジャンプします。
移動しない場合は、ここをクリックしてください。



今年も残りあと1ヶ月。
新しいことをはじめようと意気込んだこの一年、結局、例年とあまり変わらない一年で終わりそうなので、来年につなげられるよう、しばらく中断していた記事を日々書いていこうと思います。

『息子に教えるJavaScript』と銘打って書き始めたものの、教えたいことがたくさんありすぎて、思いばかりが先に行ってしまっています。
コンピュータ、算数、科学・・・。少なくとも、自分が学んできたことの多くを息子に教えたい。本当に学ぶべきことは、もっと先にあるのだから、基礎となる部分だけでも教えられればと思います。

本Blogは、プログラミングを通して息子にコンピュータを教えたいという思いで書きはじめました。コンピュータの使い方は様々ですが、仕組みを理解するという点でプログラミングを学んでほしいと考え、身近なブラウザ上で動かせるJavaScriptを教えることにしました。

今回は、Canvasを使ったサンプルはないかと部屋を見渡したところ、たまたま時計が目に入ったので、アナログ時計を表示してみたいと思います。

あまり綺麗なソースではありませんが、細かいことは気にせずに、習うより慣れろ式に、短めのサンプルを例に挙げて、教えるきっかけになればと考えています。

https://github.com/toshio/js4son/blob/master/chapter02/lesson16.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Lesson16 Clock</title>
    <style>
    html, body {
        width:    100%;
        height:   100%;
        margin:   0;
        padding:  0;
        overflow: hidden;
    }
    canvas {
        position: absolute;
    }
    </style>
  </head>
  <body>
    <canvas id="myCanvas"></canvas>

    <script>
    function drawClock() {
        var canvas  = document.getElementById("myCanvas");
        var context = canvas.getContext("2d");
        var width   = canvas.width;
        var height  = canvas.height;
        var radius  = Math.min(width, height) / 2.0 * 0.8;
        var cx      = width  / 2;
        var cy      = height / 2;

        // Time
        var date   = new Date();
        var hour   = date.getHours() % 12;
        var minute = date.getMinutes();
        var second = date.getSeconds();

        // Clear canvas
        context.beginPath();
        context.fillStyle = "white";
        context.fillRect(0, 0, width, height);

        // Circle
        context.beginPath();
        context.arc(cx, cy, radius, 0, Math.PI * 2, true);
        context.strokeStyle = "black";
        context.lineWidth   = 5;
        context.stroke();

        // Numbers
        var hours = ["Ⅻ","Ⅰ","Ⅱ","Ⅲ","Ⅳ","Ⅴ","Ⅵ","Ⅶ","Ⅷ","Ⅸ","Ⅹ","Ⅺ"];
        context.beginPath();
        context.textAlign    = "center";
        context.textBaseline = "middle";
        context.font         = Math.floor(radius * 0.15) + "px 'MS 明朝'";
        context.fillStyle    = "black";
        for (var index in hours) {
            var radiusNumber = radius * 0.85;
            var thetaNumber  = (2 * Math.PI / 12 ) * index;
            var posNumber    = calcPosition(cx, cy, radiusNumber, thetaNumber);
            context.fillText(hours[index], posNumber.x, posNumber.y);
        }

        // Hour hand
        var radiusHour = radius * 0.7;
        var thetaHour  = (2 * Math.PI / 12 ) * (hour + minute / 60 + second / 3600);
        var posHour    = calcPosition(cx, cy, radiusHour, thetaHour);
        context.beginPath();
        context.moveTo(cx,  cy);
        context.lineTo(posHour.x, posHour.y);
        context.lineWidth = 4;
        context.stroke();

        // Minute hand
        var radiusMinute = radius * 0.9;
        var thetaMinute  = (2 * Math.PI / 60) * (minute + second / 60);
        var posMinute    = calcPosition(cx, cy, radiusMinute, thetaMinute);
        context.beginPath();
        context.moveTo(cx,  cy);
        context.lineTo(posMinute.x, posMinute.y);
        context.lineWidth = 3;
        context.stroke();

        // Second hand
        var radiusSecond = radius * 0.9;
        var thetaSecond  = (2 * Math.PI / 60) * second;
        var posSecond    = calcPosition(cx, cy, radiusSecond, thetaSecond);
        context.beginPath();
        context.moveTo(cx,  cy);
        context.lineTo(posSecond.x, posSecond.y);
        context.strokeStyle = "red";
        context.lineWidth   = 1;
        context.stroke();

        // Invoke when second changed
        setTimeout(drawClock, 1000 - date.getMilliseconds());
    }

    function calcPosition(cx, cy, radius, theta) {
        return {
            x: cx + (radius * Math.sin(theta)),
            y: cy - (radius * Math.cos(theta))
        };
    }

    function resize() {
        var canvas = document.getElementById("myCanvas");
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        drawClock();
    }

    window.addEventListener("resize", resize, false);
    window.addEventListener("load",   resize, false);
    </script>
  </body>
</html>