開発環境
- macOS Sierra - Apple (OS)
- Emacs (Text Editor)
- JavaScript (プログラミング言語)
- JavaScript Library
- Safari(Web browser)
- 参考書籍
- JavaScript 第6版 (David Flanagan(著)、村上 列(翻訳)、オライリージャパン)
- JavaScriptリファレンス 第6版(David Flanagan(著)、木下 哲也(翻訳)、オライリージャパン)
アルゴリズムパズル(Anany Levitin (著)、Maria Levitin (著)、黒川 洋 (翻訳)、松崎 公紀 (翻訳)、オライリージャパン)の中級パズル、64.(八角形の作成 (Creating Octagons))をJavaScriptで。
64.(八角形の作成 (Creating Octagons))
コード(Emacs)
HTML5
<div id="graph0"></div> <label for="n0">点の個数: n = </label> <input id="n0" type="number" min="8" step="8" value="40"> <button id="polygons">八角形を生成して描画</button> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.6/d3.min.js" integrity="sha256-5idA201uSwHAROtCops7codXJ0vja+6wbBrZdQ6ETQc=" crossorigin="anonymous"></script> <script src="sample64.js"></script>
JavaScript
{ 'use strict'; Array.range = function (start, end, step) { var nums = [], i; if (step === 0) { throw { name: 'ValueError', message: 'range() arg 3 must not be zero', }; } if (step === undefined) { step = 1; } if (end === undefined) { end = start; start = 0; } if (step > 0) { for (i = start; i < end; i += step) { nums.push(i); } } else { for (i = start; i > end; i += step) { nums.push(i); } } return nums; }; let points, svg, width = 600, height = 600, padding = 50, div_graph = document.querySelector('#graph0'), input_n = document.querySelector('#n0'), input_polygons = document.querySelector('#polygons'); let getPoints = (n) => { let points = Array.range(n).map( () => [Math.random() * (width - 1) + 1, Math.random() * (height - 1) + 1] ); points.sort((p1, p2) => { let x1 = p1[0], x2 = p2[0]; if (x1 === x2) { return p1[1] - p2[1]; } return x1 - x2; }); return points; }; let drawPoints = () => { let n = parseInt(input_n.value, 10); points = getPoints(n), div_graph.innerHTML = ''; svg = d3.select('#graph0') .append('svg') .attr('width', width) .attr('height', height); svg.selectAll('circle') .data(points) .enter() .append('circle') .attr('cx', (d) => d[0]) .attr('cy', (d) => d[1]) .attr('r', 2) .attr('fill', 'green'); }; let getLineFunc = (p1, p2) => { let x1 = p1[0], x2 = p2[0]; if (x1 === x2) { throw { name: '', message: '', }; } let a = (p2[1] - p1[1]) / (x2 - x1); return (x) => a * x - a * x1 + p1[1]; }; let drawPolygons = () => { let polygons = [], color = 'blue'; let polygon = []; console.log(points); points.forEach((p, i) => { if (i % 8 === 7) { let p0 = polygon.shift(), func = getLineFunc(p0, p); let ps1 = polygon.filter((p) => func(p[0])< p[1]), ps2 = polygon.filter((p) => func(p[0])> p[1]); ps1.sort((p1, p2) => p1[0] - p2[0]); ps2.sort((p1, p2) => p2[0] - p1[0]); polygons.push([p0].concat(ps1).concat([p]).concat(ps2)); polygon = []; } else { polygon.push(p); } }); console.log(polygons); points = polygons.reduce((p1, p2) => p1.concat(p2), []); svg.selectAll('line') .data(points) .enter() .append('line') .attr('x1', (d) => d[0]) .attr('y1', (d) => d[1]) .attr('x2', (d, i) => points[i + (i % 8 === 7 ? -7 : 1)][0]) .attr('y2', (d, i) => points[i + (i % 8 === 7 ? -7 : 1)][1]) .attr('stroke', (d, i) => { if (i % 8 === 0) { color = color === 'red' ? 'green' : color === 'green' ? 'blue' : 'red'; } return color; }); }; input_n.onchange = drawPoints; polygons.onclick = drawPolygons; drawPoints(); drawPolygons(); }
0 コメント:
コメントを投稿