開発環境
- OS X Mavericks - Apple (OS)
- Dart Editor (開発環境)
- Dartium | Dart/ Structured web apps (ブラウザ, Dart VM 用 (Chromium with the Dart VM))
- Safari (ブラウザ, JavaScript 用)
- Dart (プログラミング言語)
Real World Haskell―実戦で学ぶ関数型言語プログラミング(Bryan O'Sullivan (著)、 John Goerzen (著)、 Don Stewart (著)、山下 伸夫 (翻訳)、伊東 勝利 (翻訳)、株式会社タイムインターメディア (翻訳)、オライリージャパン)の3章(型を定義し、関数を単純化する)、3.13(ガードの条件節の評価)、練習問題 12.をDartで解いてみる。
その他参考書籍
- What is Dart? [Kindle版] (O'Reilly Media) Kathy Walrath Seth Ladd (著) このブログでの感想
練習問題 12.
コード
sample.dart
import 'dart:html'; void main(){ run.onClick.listen((MouseEvent){ pre.text = window.navigator.userAgent + '\n'; try{ var nums = input_nums.value.split(',') .map((String s) => num.parse(s.trim())); if(nums.length % 2 != 0){ throw '点の集合になっていない。'; } List<Point> points = []; while(nums.length != 0){ var pairs = nums.take(2); points.add(new Point(pairs.first, pairs.last)); nums = nums.skip(2); } pre.text += '2次元平面上の点: $points\n'; var a = grahamScan(points); pre.text += 'Graham scan: $a\n'; pre.text += 'Directions: ${getDirections(a)}\n'; } catch (e){ pre.text += '$e\n'; } }); clear.onClick.listen((MouseEvent event) => pre.text = ''); } InputElement input_nums = querySelector('#input_nums'); ButtonElement run = querySelector('#run_dart'); ButtonElement clear = querySelector('#clear'); PreElement pre = querySelector('#pre0'); List<Point> grahamScan(List<Point> points){ var kernel = findLowestPoint(points); var sorted_points = sortedPoints(kernel, points); return grahamScanRecursive(kernel, sorted_points); } List<Point> grahamScanRecursive(Point kernel, List<Point> points){ if(points.length < 2){ throw 'エラー: grahamScanRecursive'; } if(points.length == 2){ var p1 = points[0]; var p2 = points[1]; var d = new Direction(p1, p2, kernel).direction; return d == 'Left turn' ? [p1, p2] : [p2]; } var p1 = points[0]; var p2 = points[1]; var p3 = points[2]; var new_points = points.sublist(3); List<Point> result = []; if(p1 == p2){ result.addAll([p1, p3]); } else if(p1 == p3){ result.add(p1); } else if(p2 == p3){ result.addAll([p1, p2]); } else if(new Direction(p1, p2, p3).direction == 'Left turn'){ result.addAll([p2, p3]); result.addAll(new_points); List<Point> new_result = [p1]; new_result.addAll(grahamScanRecursive(kernel, result)); return new_result; } else { result.addAll([p1, p3]); } result.addAll(new_points); return grahamScanRecursive(kernel, result); } Point findLowestPoint(List<Point> points){ var lowest = points.first; for(var p in points.sublist(1)){ lowest = lowest.lowerPoint(p); } return lowest; } List<Point> sortedPoints(Point kernel, List<Point> points){ var new_points = points.toList(); new_points.sort((Point p1, Point p2) => p1.comparePoint(kernel, p2)); return new_points; } List<Direction> getDirections(List<Point> points){ if(points.length < 3){ return []; } var result = []; result.add(new Direction(points[0], points[1], points[2])); result.addAll(getDirections(points.sublist(1))); return result; } class Point{ num x; num y; Point(this.x, this.y); bool operator ==(Point p) => x == p.x && y == p.y; Point lowerPoint(Point p){ var py = p.y; if(y < py){ return this; } if(y > py){ return p; } var px = p.x; if(x < px){ return this; } return p; } int comparePoint(Point kernel, Point p){ if(this == p){ return 0; } var cow = (x - kernel.x) * (p.y - kernel.y) - (y - kernel.y) * (p.x - kernel.x); if(cow > 0){ return -1; } if(cow < 0){ return 1; } if(x < p.x){ return -1; } return 1; } String toString() => '($x, $y)'; } class Direction{ String direction; Direction(Point a, Point b, Point c){ var cow = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x); direction = cow > 0 ? 'Left turn' : cow == 0 ? 'Collinear' : 'Right turn'; } String toString(){ return direction; } }
0 コメント:
コメントを投稿