2016年8月31日水曜日

開発環境

Pythonからはじめる数学入門 (Amit Saha (著)、黒川 利明 (翻訳)、オライリージャパン)の5章(集合と確率を操作する)、5.4(プログラミングチャレンジ)、問題5-5(円の領域を推定する、πの値を推定する)をJavaScript(とarray.js)で取り組んでみる。

問題5-5(円の領域を推定する、πの値を推定する)

コード(Emacs)

HTML5

<div id="graph0"></div>
Area: <span id="area0"></span>, Estimated (<span id="darts1"></span> darts):
<span id="estimated0"></span>, π: <span id="pi0"></span>
<br>
<label for="radius0">
  Radius:
</label>
<input id="radius0" type="number" min="1" step="1" value="2">
<label for="darts0">
  darts:
</label>
<input id="darts0" type="number" min="1" step="1" value="1000">

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script>
<script src="array.js"></script>
<script src="sample5.js"></script>

JavaScript

(function () {
    'use strict';
    var width = 600,
        height = 600,
        padding = 50,
        
        div_graph = document.querySelector('#graph0'),
        span_area = document.querySelector('#area0'),
        span_darts = document.querySelector('#darts1'),
        span_estimated = document.querySelector('#estimated0'),
        span_pi = document.querySelector('#pi0'),
        input_radius = document.querySelector('#radius0'),
        input_darts = document.querySelector('#darts0'),
        inputs = [input_radius, input_darts],

        randomDarts,
        estimateAreaAndPi,
        drawGraph,
        display;

    randomDarts = function (radius, darts) {
        var i,
            points = [],
            x,
            y;

        for (i = 0; i < darts; i += 1) {        
            x = Math.random() * (2 * radius) - radius;
            y = Math.random() * (2 * radius) - radius;
            points.push([x, y]);
        }
        return points;
    };

    estimateAreaAndPi = function (radius, points) {
        var area = Math.pow(2 * radius, 2),
            n = 0,
            m = 0,
            r,
            ratio;

        points.forEach(function (point) {
            r = Math.sqrt(Math.pow(point[0], 2) + Math.pow(point[1], 2));
            if (r <= radius) {
                n += 1;
            } else {
                m += 1;
            }
        });
        ratio = n / (n + m);
        return [area * ratio, 4 * ratio];
    };

    drawGraph = function (radius, points) {
        var svg,
            xscale,
            xaxis,
            yscale,
            yaxis,
            red = Math.floor(Math.random() * 256),
            green = Math.floor(Math.random() * 256),
            blue = Math.floor(Math.random() * 256);

        xscale = d3.scaleLinear()
            .domain([-radius, radius])
            .range([padding, width - padding]);
        yscale = d3.scaleLinear()
            .domain([-radius, radius])
            .range([height - padding, padding]);
        
        xaxis = d3.axisBottom().scale(xscale);
        yaxis = d3.axisLeft(yscale);
        
        div_graph.innerHTML = '';

        svg = d3.select('#graph0')
            .append('svg')
            .attr('width', width)
            .attr('height', height);

        svg.append('line')
            .attr('x1', xscale(-radius))
            .attr('y1', yscale(0))
            .attr('x2', xscale(radius))
            .attr('y2', yscale(0))
            .attr('stroke', 'black');
        svg.append('line')
            .attr('x1', xscale(0))
            .attr('y1', yscale(-radius))
            .attr('x2', xscale(0))
            .attr('y2', yscale(radius))
            .attr('stroke', 'black');
        svg.append('circle')
            .attr('cx', xscale(0))
            .attr('cy', xscale(0))
            .attr('r', (width - 2 * padding) / 2)
            .attr('fill', 'rgba(' + red + ', ' + green + ', ' + blue + ', 0.5)');

        svg.selectAll('circle')
            .data(points)
            .enter()
            .append('circle')
            .attr('cx', function (d) {
                return xscale(d[0]);
            })
            .attr('cy', function (d) {
                return yscale(d[1]);
            })
            .attr('r', 1)
            .attr('fill', 'blue');
        
        svg.append('g')
            .attr('transform', 'translate(0, ' + (height - padding) + ')')
            .call(xaxis);
        svg.append('g')
            .attr('transform', 'translate(' + padding + ', 0)')
            .call(yaxis);
    };

    display = function () {
        var radius = parseInt(input_radius.value, 10),
            darts = parseInt(input_darts.value, 10),
            points,
            area,
            estimated,
            estimated_area,
            estimated_pi;

        points = randomDarts(radius, darts);
        area = Math.PI * Math.pow(radius, 2);
        estimated = estimateAreaAndPi(radius, points);
        estimated_area = estimated[0];
        estimated_pi = estimated[1];
        span_area.innerText = area;
        span_darts.innerText = darts;
        span_estimated.innerText = estimated_area;
        span_pi.innerText = estimated_pi;
        drawGraph(radius, points);
    };

    inputs.forEach(function (input) {
        input.onchange = display;
    });

    display();
}());
Area: , Estimated ( darts): , π:

0 コメント:

コメントを投稿