<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
		xmlns:xhtml="http://www.w3.org/1999/xhtml"
>

<channel>
	<title>クレコ &#187; Ruby</title>
	<atom:link href="http://creco.net/tag/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://creco.net</link>
	<description>East or west, home is best.</description>
	<lastBuildDate>Fri, 27 Nov 2009 13:26:56 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/tag/ruby/feed/" />
		<item>
		<title>ジオポの符号化、復号化をいろんな言語で書いてみる Part.2</title>
		<link>http://creco.net/2009/03/10/write_codes_in_variaous_languages_2/</link>
		<comments>http://creco.net/2009/03/10/write_codes_in_variaous_languages_2/#comments</comments>
		<pubDate>Tue, 10 Mar 2009 10:52:19 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[日記]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[ジオポ]]></category>

		<guid isPermaLink="false">http://creco.net/2009/03/10/write_codes_in_variaous_languages_2/</guid>
		<description><![CDATA[いろんな言語で書いてみると楽しい。他の人の役に立つサンプルコードというよりも、自分のために書いてるところが大きいです。
そんなわけで、今回はC++、Perl、RubyとPythonで書いてみた。
 
サンプルコード
C+ [...]]]></description>
			<content:encoded><![CDATA[<p>いろんな言語で書いてみると楽しい。他の人の役に立つサンプルコードというよりも、自分のために書いてるところが大きいです。</p>
<p>そんなわけで、今回はC++、Perl、RubyとPythonで書いてみた。</p>
<p> <span id="more-151"></span><br />
<h4>サンプルコード</h4>
<h5>C++</h5>
<p>
<div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:cd35fe8e-ef86-4987-a6b6-0b8bd58ba685" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="c">/*
 * GeoPo Encode in C++
 * @author : Shintaro Inagaki
 * @param geopo, lat lng, scale (pointer)
 */
void geopoEncode(char *geopo, double &amp;lat, double &amp;lng, int &amp;scale)
{
	// 64characters (number + big and small letter + hyphen + underscore)
	char chars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
	int i;

	// Change a degree measure to a decimal number
	lat = (lat + 90) / 180 * pow(8.0, 10.0);
	lng = (lng + 180) / 360 * pow(8.0, 10.0);

	// Compute a GeoPo code from head and concatenate
	for(i = 0;i &lt; scale;i++){
		geopo[i] = chars[(int)(floor(fmod(lat / pow(8.0, 9.0 - i), 8.0)) + floor(fmod(lng / pow(8.0, 9.0 - i), 8.0)) * 8)];
	}
	geopo[i] = '\0';
}		

/*
 * GeoPo Decode in C++
 * @author : Shintaro Inagaki
 * @param geopo, lat lng, scale (pointer)
 */
void geopoDecode(char *geopo, double &amp;lat, double &amp;lng, int &amp;scale)
{
	// 64characters (number + big and small letter + hyphen + underscore)
	char chars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
	int order, i;

	scale = strlen(geopo);

	for(i = 0;i &lt; scale;i++){
		// What number of character that equal to a GeoPo code (0-63)
		order = (strchr(chars, geopo[i]) - chars);
		// Lat/Lng plus geolocation value of scale
		lat = lat + fmod(order, 8.0) * pow(8.0, 9.0 - i);
		lng = lng + floor((double)order / 8.0) * pow(8.0, 9.0 - i);
	}
	// Change a decimal number to a degree measure, and plus revised value that shift center of area
	lat = lat * 180 / pow(8.0, 10.0) - 90 + 180 / pow(8.0, scale) / 2;
	lng = lng * 360 / pow(8.0, 10.0) - 180 + 360 / pow(8.0, scale) / 2;
}	</pre>
</div>
<p>専らライトウェイトなインタプリタ言語ばかりやってるので、C++とかJavaは仕事で扱ったくらいしか経験なく、コンパイル環境すら整えてないので、MicrosoftのVisual C++をダウンロードする作業から開始した。</p>
<p>標準ライブラリのstdio.h、math.hとstring.h を使ってるから、適宜importしてください。Cではコンパイルしてないけど、Cでもokなんじゃないかな？</p>
<p>関数とかは前回のObjective-Cとほとんど同じ。<strong>pow()</strong>、<strong>fmod()</strong>、<strong>floor()</strong>とか。</p>
<p>今回はcharsを配列形式のcharにしてジオポ符号を取り出す形。最後にヌル文字を加えるのをお忘れ無く。</p>
<p>復号化は、<strong>strchr()</strong>でジオポの符号を検索してその位置を返すんだけど、返す型がポインタ。だから、そのポインタの値をcharsの先頭ポインタで引いてやることによって、位置のintを取り出すようにした。</p>
<p>Visual C++って使いづらくない？慣れだと思うけど使っててアレルギーでそうだった&#8230;特にポインタミスって色んなアプリを引き連れにハングアップさせたり&#8230;（自分が悪いけど）</p>
<h5>Perl</h5>
<p><div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:2f89d35f-2a99-4b20-ae96-abaea53be71d" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="php">#
# GeoPo Encode in Perl
# @author : Shintaro Inagaki
# @param %location (Hash) [lat (Float), lng (Float), scale(Int)]
# @return $geopo (String)
#
sub geopoEncode(%location) {
	# 64characters (number + big and small letter + hyphen + underscore)
	$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";

	$geopo = "";
	$lat = $location{'lat'};
	$lng = $location{'lng'};
	$scale = $location{'scale'};

	# Change a degree measure to a decimal number
	$lat = ($lat + 90) / 180 * 8 ** 10;
	$lng = ($lng + 180) / 360 * 8 ** 10;

	# Compute a GeoPo code from head and concatenate
	for($i = 0; $i &lt; $scale; $i++) {
		$geopo .= substr($chars, int($lat / 8 ** (9 - $i) % 8) + int($lng / 8 ** (9 - $i) % 8) * 8, 1);
	}
	return $geopo;
}		

#
# GeoPo Decode in Perl
# @author : Shintaro Inagaki
# @param $geopo (String)
# @return %location (Hash) [lat (Float), lng (Float), scale(Int)]
#
sub geopoDecode($geopo) {
	# 64characters (number + big and small letter + hyphen + underscore)
	$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
	# Hash for geolocation
	%location = ();

	for ($i = 0; $i &lt; length($geopo); $i++) {
		# What number of character that equal to a GeoPo code (0-63)
		$order = index($chars, substr($geopo, $i, 1));
		# Lat/Lng plus geolocation value of scale
		$location{'lat'} += $order % 8 * 8 ** (9 - $i);
		$location{'lng'} += int($order / 8) * 8 ** (9 - $i);
	}

	# Change a decimal number to a degree measure, and plus revised value that shift center of area
	$location{'lat'} = $location{'lat'} * 180 / 8 ** 10 - 90 + 180 / 8 ** length($geopo) / 2;
	$location{'lng'} = $location{'lng'} * 360 / 8 ** 10 - 180 + 360 / 8 ** length($geopo) / 2;
	$location{'scale'} = length($geopo);

	return %location;
}		</pre>
</div>
<p>今から5年くらい前はPHPじゃなくてPerlばかり使ってた。あまりたいしたコードは書いてないけど、どんなスパゲッティコードでもソースを読み取ることができる能力は自慢ｗ まぁ、僕自身がスパゲッティを生産してたわけだけど。</p>
<p>PHPとほぼ変わらない。ユーザ関数は<strong>sub</strong>でも<strong>function</strong>でも、連想配列（ハッシュ）は<strong>%hoge</strong>と<strong>$hoge{&#8216;hoge&#8217;}</strong>みたいになるので注意。ちなみに、ただの配列だと@hoge</p>
<p><strong>%</strong>で余り、<strong>**</strong>でべき乗、<strong>int()</strong>で整数化、<strong>length()</strong>で長さ、<strong>+</strong>で文字の結合、<strong>substr()</strong>で文字の切り出し、<strong>index()</strong>で文字の位置。</p>
<p>PerlもモダンPerlが話題になってるから、再勉強してみようかな。使ってた当時は豊富なライブラリ・モジュールにお世話になりっぱなしで、クラスすら作った経験ないんだよね。</p>
<h5>Ruby</h5>
<p><div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:1dc2a9c3-3934-4212-b815-653c51df37dd" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="ruby">#
# GeoPo Encode in Ruby
# @author : Shintaro Inagaki
# @param location (Hash) [lat (Float), lng (Float), scale(Int)]
# @return geopo (String)
#
def geopoEncode(location)
	# 64characters (number + big and small letter + hyphen + underscore)
	chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"

	geopo = ""
	lat = location['lat']
	lng = location['lng']
	scale = location['scale']

	# Change a degree measure to a decimal number
	lat = (lat + 90.0) / 180 * 8 ** 10; # 90.0 is forced FLOAT type when lat is INT
	lng = (lng + 180.0) / 360 * 8 ** 10; # 180.0 is same

	# Compute a GeoPo code from head and concatenate
	for i in 0..scale
		geopo += chars[(lat / 8 ** (9 - i) % 8).floor + (lng / 8 ** (9 - i) % 8).floor * 8, 1];
	end
	return geopo;
end		

#
# GeoPo Decode in Ruby
# @author : Shintaro Inagaki
# @param geopo (String)
# @return location (Hash) [lat (Float), lng (Float), scale(Int)]
#
def geopoDecode(geopo)
	# 64characters (number + big and small letter + hyphen + underscore)
	chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"
	# Hash for geolocation
	location = {}

	lat = 0.0
	lng = 0.0
	scale = geopo.size # Scale is length of GeoPo code
	order = 0

	for i in 0..(scale - 1)
		# What number of character that equal to a GeoPo code (0-63)
		order = chars.index(geopo[i])
		# Lat/Lng plus geolocation value of scale
		lat = lat + order % 8 * 8 ** (9 - i)
		lng = lng + (order / 8).floor * 8 ** (9 - i)
	end

	# Change a decimal number to a degree measure, and plus revised value that shift center of area
	location['lat'] = lat * 180 / 8 ** 10 - 90 + 180 / 8 ** scale / 2
	location['lng'] = lng * 360 / 8 ** 10 - 180 + 360 / 8 ** scale / 2
	location['scale'] = scale

	return location
end		</pre>
</div>
<p>Rubyも必要になった経験がなかったから、あまり知らない。だけど、ライトウェイトなインタプリタ言語はひとつの言語を知っていれば、サンプルコードを真似して書ける。その中でもRubyは一番とっつきやすい（PHPからPerlから乗換え）と思う。</p>
<p>ユーザ関数は<strong>def</strong>でスタート<strong>end</strong>で終わる。forループも<strong>for</strong>でスタートendで終わる。自然とインデントするので見やすい。連想配列（ハッシュ）も普通の変数と区別なし。</p>
<p><strong>%</strong>で余り、<strong>**</strong>でべき乗、<strong>floor()</strong>で切り捨て、<strong>size</strong>と<strong>length</strong>メソッドどっちでも文字の長さ、<strong>+</strong>で文字の結合、配列と同じ操作で文字列から文字を取り出せる（<strong>slice</strong>メソッド使ってもいい）、<strong>index</strong>で文字の位置</p>
<p>PHP版Ruby on RailsといわれてるCodeIgniterがわかりつつあるので、RoRに移行してもスムースにいけるかな。ただ、本当にRubyじゃないとダメっていう案件がなさすぎる。</p>
<h5>Python</h5>
<p><div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:d39098f2-8ad1-4ca5-a59f-9243624cbab3" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="py">#
# GeoPo Encode in Python
# @author : Shintaro Inagaki
# @param location (Dictionary) [lat (Float), lng (Float), scale(Int)]
# @return geopo (String)
#
def geopoEncode(location) :
       # 64characters (number + big and small letter + hyphen + underscore)
       chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"

       geopo = ""
       lat = location['lat']
       lng = location['lng']
       scale = location['scale']

       # Change a degree measure to a decimal number
       lat = (lat + 90.0) / 180 * 8 ** 10 # 90.0 is forced FLOAT type when lat is INT
       lng = (lng + 180.0) / 360 * 8 ** 10 # 180.0 is same

       # Compute a GeoPo code from head and concatenate
       for i in range(scale):
               order = int(lat / (8 ** (9 - i)) % 8) + int(lng / (8 ** (9 - i)) % 8) * 8
               geopo = geopo + chars[order]

       return geopo		

#
# GeoPo Decode in Python
# @author : Shintaro Inagaki
# @param geopo (String)
# @return location (Dictionary) [lat (Float), lng (Float), scale(Int)]
#
def geopoDecode(geopo) :
       # 64characters (number + big and small letter + hyphen + underscore)
       chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"

       lat = 0.0
       lng = 0.0
       scale = len(geopo) # Scale is length of GeoPo code
       order = 0

       for i in range(scale):
               # What number of character that equal to a GeoPo code (0-63)
               order = chars.find(geopo[i])
               # Lat/Lng plus geolocation value of scale
               lat = lat + order % 8 * 8 ** (9 - i)
               lng = lng + int(order / 8) * 8 ** (9 - i)

       # Change a decimal number to a degree measure, and plus revised value
that shift center of area
       location['lat'] = lat * 180 / 8 ** 10 - 90 + 180 / 8 ** scale / 2
       location['lng'] = lng * 360 / 8 ** 10 - 180 + 360 / 8 ** scale / 2
       location['scale'] = scale

       return location		</pre>
</div>
<p>GoogleのクラウドでHelloWorldくらいまで勉強した気がｗ その後、GPSロガーとのシリアル通信プログラム（PySerial）書いたときに大活躍！ライトウェイトな言語なくせして、ネイティブなデバイスが簡単に扱えた衝撃はでかかった。</p>
<p>&#8230;えっと。あまりにもRubyと変わらないのであまり書くこともないという。<br />
  <br />Python最大の特徴であるインデントに注意して、あとは<strong>find()</strong>が文字の位置、<strong>range()</strong>で範囲が便利になるよってくらい。</p>
<p>そうだそうだ、RubyとPythonは符号化のローカル変数の代入時にわざとfloatの数値を足してあげて、intで引数がわたされた場合でも強制的にfloatになるようにしてあるよ。</p>
<p>Pythonの話題もよく耳にするようになってきたし、何よりソースコードが強制的にキレイになるっていうのがいいね。</p>
<h4>まとめ</h4>
<p>コンバイラ言語はめんどくさい。ライトウェイト言語ばんざーい。</p>
<p>暇があったら、Haskell（関数型言語）に挑戦したいね。</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2009/03/10/write_codes_in_variaous_languages_2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2009/03/10/write_codes_in_variaous_languages_2/" />
	</item>
	</channel>
</rss>
