ジオキャッシングは、アウトドアの楽しみとパズルを解く楽しみを組み合わせたものです。アウトドアもパズルも好きなら、きっと大ファンになるはずです。 地元のジオキャッシングサイトには、すべてのキャッシュのGPS座標が掲載されていますが、それらを効率よく集めるルートを作成する機能は_ありません_。 たまたま、手元のマシンには経路探索ソフトウェアがインストールされていますが、それはジオキャッシングサイトとは異なるGPS形式を使っています。 そのデータを経路探索ソフトウェアに読み込ませるには、サイトにある各GPS座標の緯度と経度について、度と半球を解析する必要があります。
ここでのタスクは、GPSの座標を解析することです。 各座標は、半球を明示する十進度形式の変種で書式化されています:
<LATITUDE_DEGREES> <LATITUDE_HEMISPHERE>, <LONGITUDE_DEGREES> <LONGITUDE_HEMISPHERE>
各構成要素に使える値は次のとおりです:
<LATITUDE_DEGREES>:0..90の範囲(両端を含む)の浮動小数点数<LATITUDE_HEMISPHERE>:NまたはS
<LONGITUDE_DEGREES>:0..180の範囲(両端を含む)の浮動小数点数<LONGITUDE_HEMISPHERE>:EまたはW
たとえば、"48.8584 N, 2.2945 E"は次のように解析されます:
<LATITUDE_DEGREES>:48.8584<LATITUDE_HEMISPHERE>:N<LONGITUDE_DEGREES>:2.2945<LONGITUDE_HEMISPHERE>:E11個のタスクに分けて、GPSの座標を少しずつ解析していきます。 ここでは、Prologの確定節文法(DCG)サポートを使います。これは構造化されたテキストを解析するために設計されたものです。
まずは始めやすいように、スタブファイルにはすでに次のようにdcg/basicsライブラリが読み込まれています:
:- use_module(library(dcg/basics)).
commaルールを実装して、1つのカンマ(",")を解析できるようにします:
?- string_codes(",", Codes), phrase(comma, Codes).
spaceルールを実装して、1つの空白(" ")を解析できるようにします:
?- string_codes(" ", Codes), phrase(space, Codes).
spaceルールを変更して、改行を除く_すべての_空白文字を解析できるようにします:
?- string_codes("\t", Codes), phrase(space, Codes).
?- string_codes("\n", Codes), phrase(space, Codes).
false.
緯度の半球は"N"か"S"のどちらかで、それぞれnorthまたはsouthというアトムに解析されます。
latitude_hemisphereルールを実装して、緯度の半球を解析できるようにします:
?- string_codes("N", Codes), phrase(latitude_hemisphere(Hemisphere), Codes).
Hemisphere = north.
経度の半球は"E"か"W"のどちらかで、それぞれeastまたはwestというアトムに解析されます。
longitude_hemisphereルールを実装して、経度の半球を解析できるようにします:
?- string_codes("E", Codes), phrase(longitude_hemisphere(Hemisphere), Codes).
Hemisphere = east.
緯度や経度の度は、浮動小数点数として定義されています。
degreesルールを実装して、浮動小数点数を解析できるようにします:
?- string_codes("748.012", Codes), phrase(degrees(Degrees), Codes).
Degrees = 748.012.
緯度の度は、ただの浮動小数点数ではなく、0..90の範囲(両端を含む)の浮動小数点数です。
latitude_degreesルールを実装して、上記の範囲を使って緯度の度を解析できるようにします:
?- string_codes("48.745", Codes), phrase(latitude_degrees(Degrees), Codes).
Degrees = 48.745.
?- string_codes("117.844", Codes), phrase(latitude_degrees(Degrees), Codes).
false.
経度の度は、ただの浮動小数点数ではなく、0..180の範囲(両端を含む)の浮動小数点数です。
longitude_degreesルールを実装して、上記の範囲を使って経度の度を解析できるようにします:
?- string_codes("178.773", Codes), phrase(longitude_degrees(Degrees), Codes).
Degrees = 178.773.
?- string_codes("-22.523", Codes), phrase(longitude_degrees(Degrees), Codes).
false.
緯度には、度と半球という2つの部分があり、それらは空白で区切られています。
latitudeルールを実装して、緯度を解析できるようにします:
?- string_codes("56.101 N", Codes), phrase(latitude(Degrees, Hemisphere), Codes).
Degrees = 56.101,
Hemisphere = north.
緯度には、度と半球という2つの部分があり、それらは空白で区切られています。
latitudeルールを実装して、緯度を解析できるようにします:
?- string_codes("143.889 W", Codes), phrase(longitude(Degrees, Hemisphere), Codes).
Degrees = 143.889,
Hemisphere = west.
座標には、緯度と経度という2つの部分があり、それらはカンマとそれに続く空白で区切られています。
coordinateルールを実装して、緯度(度と半球)の両方を解析できるようにします:
?- string_codes("48.8584 N, 2.2945 E", Codes), phrase(coordinate(Latitude, LatitudeHemisphere, Longitude, LongitudeHemisphere), Codes).
Latitude = 48.8584,
LatitudeHemisphere = north,
Longitude = 2.2945,
LongitudeHemisphere = east.