格子点の列挙
30分プログラム、その156。格子点の列挙。
二次元平面上の格子点(X,Y座標がともに整数の点)を、原点から近い順に列挙してください。
同じ距離の点はどういう順番でも構いませんが、可能であればX軸に一番近い第一象限の点から原点を中心として反時計回りの順に列挙してください。 列挙の方法は、1行に一つの点の、X,Y座標を出力することとします。サンプル出力
0, 0 1, 0 0, 1 -1, 0 0, -1 1, 1 -1, 1 1, -1 -1, -1 2, 0
使い方
$ ruby lattice.rb <0,0> <1,0> <0,1> <-1,0> <0,-1> <1,1> <-1,1> <1,-1> <-1,-1> <2,0>
ソースコード
反時計回りで、どちらが先にくるかはアークタンジェントで計算する。
#! /opt/local/bin/ruby -w # -*- mode:ruby; coding:utf-8 -*- # # lattice.rb - # # Copyright(C) 2007 by mzp # Author: MIZUNO Hiroki <hiroki1124@gmail.com> # http://mzp.sakura.ne.jp/ # # Timestamp: 2007/10/06 18:05:40 # # This program is free software; you can redistribute it and/or # modify it under the same terms as Ruby itself. # # 配列でこれを実現すると、flattenで展開されてしまう Point = Struct.new 'Point',:x,:y class Point def to_s "<#{x},#{y}>" end end range = -20..20 points = range.map{|x| range.map{|y| Point.new x,y } }.flatten def dist(point) point.x*point.x + point.y*point.y end def atan(point) r = Math.atan2 point.y,point.x if r < 0 then Math::PI - r else r end end puts points.sort{|a,b| d = dist(a) <=> dist(b) if d == 0 then atan(a) <=> atan(b) else d end }[0,1000]