著者アーカイブ 杉浦

著者:杉浦

if文の様な正規表現である先読み、戻り読み

 正規表現の文法には先読み、戻り読みと呼ばれる記法があります。戻り読みは後読みとも呼ばれます。ここではサクラエディタのヘルプファイルに倣って戻り読みと記述します。

(?=式) 先読み
(?!式) 否定先読み
(?<=式) 戻り読み
(? 否定戻り読み

 この記法は英語ではlookahead,lookbihindと呼ばれます。正規表現の途中でこの記法が現れた時、正規表現エンジンは先読み後読みで括られた部分式が文字列のまだ読んでいない先の方やもう読み終わった戻った方にマッチするかしないかを判断します。このマッチング判断は読んでいる文字列の位置を変えません。(?=)(?!)(?<=)(?
 この正規表現はhogeを含まない文字列中のfugaにマッチする正規表現です。先読みはまだ読んでいない先の方を見るだけ、lookaheadするだけで文字列を消費しない記法です。そのため、以下の様なマッチもできます。

 ハイライト部分がマッチしている部分です。行頭から見て.*hogeが成り立たない行のfugaをマッチしているわけです。

著者:杉浦

UTC、UNIX時間、ユリウス通日

 システムにおいて暦の変換処理というのは往々にして面倒なものです。慣れ親しんだ近年の年月日時分秒でさえ一月の長さの違い、閏日あたりが手間です。これが縁もゆかりもなさそうなイスラム常用暦やインド国定暦になると大変です。そのような手間を省くために世界中で利用する事を目的とした暦があります。UTC、UNIX時間、ユリウス通日はそのような暦です。
 UTC(協定世界時)は世界中を対象としたシステムの基盤としてよく使われる暦です。UTCは非常に正確に時間を刻む原子時を元にしています。地球の自転一周が一日となる様に、変化する自転の周期に合わせてUTCには適宜閏秒が挿入されます。UTCを基準に世界各地の標準時、タイムゾーンなどが決められています。GPS衛星に組み込まれている原子時計もこのUTCに同期して開始されました。
 コンピュータの世界においてよく用いられる暦の単位のひとつがUNIX時間です。UNIX時間はUTC1970年1月1日0時0分0秒からの秒数で表される暦です。分も閏もありません。UNIX時間はとにかく扱いが簡単な暦です。この点からよくコンピュータシステムの内部で用いられます。ユーザに向けて表示する時点ではその時々に合った暦に変換するわけです。
 世界にはUTC1970年1月1日0時0分0秒の記録もあり、各地各時の暦はまちまちです。ユリウス通日はそのような過去の出来事を統一した日付で扱うための暦です。ユリウス通日は紀元前4713年1月1日正午からの経過日数で表されます。ユリウス通日を用いると元禄15年12月14日=グレゴリオ暦1703年1月30日の様な比較が簡単になり餡巣。
 GNSS衛星による測位には時刻が密接にかかわっています。GNSS衛星における時刻の話にはUTC、UNIX時間、ユリウス通日がよくでます。
 国立天文台の暦計算室には、この手の話が多く詳しく載っています。

著者:杉浦

OnlinePHPFunctionsの紹介

 OnlinePHPFunctions – Test PHP functions onlineはPHPのオンライン実行環境です。要は自分でサーバを立てずともPHPを実行できる簡単な環境です。
 OnlinePHPFunctionsの主な機能はSandboxとPHP Functionsです。Sandboxでは下図の様な簡単なエディタでPHPを記述、実行できます。

 OnlinePHPFunctionsの特に好きな点は様々なverのPHPを容易に動かせる点です。4.4.9~7.2.4まで様々な環境があり、コードが使えるか使えないかを試せます。例えばPHPにおいて配列の定義構文としてarray()の代わりに[]が使えるようになったのはPHP5.4からです。そのため先ほどのコードの設定をRun on PHP version:5.3.0に変更すると次の様になります。

 使えない構文として文法エラーをもらうことなりました。PHP Functionsではこのサンドボックス機能を活かして実際に動くPHPの関数を見ることが出来ます。

著者:杉浦

問題の細分化とソースコードの関数化

 よく関数にまとめることでソースコードが読みやすくなる、再利用しやすくなると言われますが、いきなりその様ことだけ知ってもすぐにできるものではありません。関数化の指針の一つに問題の細分化というものがあります。これは分割された小さな問題ごとに関数にしていくというやり方です。例えば次のコードがあります。

// 与えられた緯度経度に最も近い 'array' の要素を返す。
// 地球が完全な球体であることを前提としている。
var findClosestLocation = function (lat, lng, array) {
	var closest;
	var closest_dist = Number.MAX_VALUE;
	for (var i = 0; i < array.length; i += 1) {
		// 2 つの地点をラジアンに変換する。
		var lat_rad = radians(lat);
		var lng_rad = radians(lng);
		var lat2_rad = radians(array[i].latitude);
		var lng2_rad = radians(array[i].longitude);
		// 「球面三角法の第二余弦定理」の公式を使う。
		var dist = Math.acos(Math.sin(lat_rad) * Math.sin(lat2_rad) +
				Math.cos(lat_rad) * Math.cos(lat2_rad) *
				Math.cos(lng2_rad - lng_rad));
		if (dist < closest_dist) {
			closest = array[i];
			closest_dist = dist;
		}
	}
	return closest;
};
Dustin Boswell; Trevor Foucher. リーダブルコード (Kindle の位置No.1930-1939). 株式会社オライリー・ジャパン. Kindle 版. 

 これはコードの最上部のコメントにあるように、与えられた緯度経度に最も近い 'array' の要素を返す、ことが最終目的の関数です。この目的を達成するためにこのコードは、2地点間の距離を算出する、最小の距離になる'array'の要素を発見する、という二つの問題を解いています。前者の2地点間の距離を算出する、という問題は最終目的から分割して考えられます。分割するという考えに沿ってコードを改造すると次の様になります。

// 与えられた緯度経度に最も近い 'array' の要素を返す。
// 地球が完全な球体であることを前提としている。
var findClosestLocation = function (lat, lng, array) {
	var closest;
	var closest_dist = Number.MAX_VALUE;
	var dist = spherical_distance(lat, lng, array[i].latitude, array[i].longitude);
	for (var i = 0; i < array.length; i += 1) {
		if (dist < closest_dist) {
			closest = array[i];
			closest_dist = dist;
		}
	}
	return closest;
};
function spherical_distance(lat, lng, lat_2, lng_2){
	//地点(lat,lng)と地点(lat_2,lng_2)の球面距離を返す
	// 2 つの地点をラジアンに変換する。
	var lat_rad = radians(lat);
	var lng_rad = radians(lng);
	var lat2_rad = radians(lat_2);
	var lng2_rad = radians(lng_2);
	// 「球面三角法の第二余弦定理」の公式を使う。
	return Math.acos(Math.sin(lat_rad) * Math.sin(lat2_rad) +
		Math.cos(lat_rad) * Math.cos(lat2_rad) *
		Math.cos(lng2_rad - lng_rad));
}

 最初より簡単な関数であるfindClosestLocationとspherical_distanceの二つが出来ました。また、この関数化は再利用等のコードの変更を容易にします。例えば、findClosestLocation中のspherical_distance(lat, lng, array[i].latitude, array[i].longitude)という部分は呼び出す関数名の変更だけで同じような度単位の二地点の緯度経度を引数にする別の関数を用いることが出来ます。二地点間の球面距離の算出というのは多用します。
 問題の細分化の基準として意図と実装の乖離があります。あるコードを書いている時、そのコードに当初と別の目的が存在するならば、それは別の問題である、というものです。

著者:杉浦

正規表現の最短一致指定子としての”?”

 正規表現には”*”、”+”、”{m,n}”などの様な繰り返しの量指定子があります。これら量指定子はそのままの場合、最長のマッチになるようにマッチングを行います。具体的には下図です。
 
 ”(a+)(a+)”で文字列”aaaaa”をマッチさせました。m[1]にはグループ1である最初のカッコの”a+”にマッチしたaが、m[2]にはグループ2である二つ目のカッコの”a+”にマッチしたaが、格納されています。最長のマッチになる様にマッチングを行う、というのは、”m[1]=aaaa”とあるようにマッチ全体が成立する範囲でできる限り多くの文字列を含もうとする動作のことです。正規表現全体のマッチが成立しなくなるまで、マッチングを続けるとも言えます。逆に最短になるようにマッチを行う方法もあり、その指定子が”?”です。”*?”や”+?”の様に繰り返し指定子の直後に”?”をつけることで最短マッチになります。最短マッチの例が下図です。
 
 ”(a+?)(a+)”で文字列”aaaaa”をマッチさせました。先ほど同様にm[1]、m[2]にそれぞれのグループが格納されています。今度は”m[1]=a”とあります。最短になるようなマッチです。この場合、繰り返し指定子がマッチしたらすぐにマッチングを終了するという動作になります。そのため”a+”が成立する”a”一文字でグループ1の部分のマッチングが終了しました。
 最短一致指定子が有効なのは例えばタグの様な特定の文字で括られたものの検索です。”<.*?>“とした場合、<の次に初めて>が出た時点でマッチングを終了してくれます。逆にダメなパターンでありがちなのは”$”や”\z”の様な行末指定です。頻繁にマッチ終了と行末か否かの判断が繰り返されて実行時間が遅くなります。

著者:杉浦

アイコン素材集FLATICON

 フリー素材集というものはいくらあっても足りません。FLATICONはアイコン検索エンジンです。検索対象はFLATICONに登録されたアイコンのみですが、その数は2018/07/27時点で976,000と膨大です。そして登録されたアイコンの多くはフリー素材です。

 様々な人や団体が、FLATICONにアイコンを登録するだけあって、人気の指数やアイコンのパッケージ化、タグ付けといった便利なカスタマイズ要素が多々あります。ただ、アイコンの画風で違いを付けにくく信用や声望で成り立ってるようなのでクレジット表記、クリエイティブコモンズには特に注意が必要です。
関連記事
【フリー素材】アイコン素材なら商用利用可の「icooon-mono」がおすすめ
ウィキメディア・コモンズの紹介

著者:杉浦

正規表現の難題、入れ子構造

 正規表現は便利な技法です。一行ほどの短い文字列で様々な文字列を表現できます。一行で動作させる単純な動作のためか実装されている正規表現の多くは後方参照以外の参照可能な記憶領域を持ちません。入れ子構造を正規表現で表そうとした場合、この記憶領域が無いという仕様が大きくのしかかってきます。
 単純に()の入れ子を考えてみます。

(()(()))

 人間が見やすいようにインデントを付けます。


(
	()
	(
		()
	)
)

 入れ子が正しく結ばれているか、どの始点がどの終点に対応しているかを考えるためには記憶領域が必要になります。
 正しく結ばれているかは、次のルールを守ったまま文字列の終わりまで読み取り切れるか否かで確認できます。
・終点を読み込んだ時、対応する始点が存在する
・読み取り終わった時、今まで読み取った始点、終点の数が等しい
最新以外の始点についての情報が無い場合、対応する始点が存在するか否かがわからず、入れ子の確認ができません。正規表現は後方参照以外に記憶領域を持ちません。このため多くの正規表現は入れ子構造を読み取ることができません。余談ですがデータ構造のひとつであるスタック構造を用いると簡単に入れ子を読み取ることが出来ます。下図はスタック構造のgifです。始点を積み、終点を読んだら始点を一つ取り出す、という動作を繰り返すことで実装できます。
 正規表現には方言がある、と言われるほど、実装が多種多様で様々な拡張がなされています。perlやphpの様なプログラミング言語の一部では正規表現の再帰呼び出しが実装されています。再帰は自身の処理中に自身を呼び出すことが可能な動作です。これで始点を積み上げ、終点で始点を打ち消す、というスタック処理をそのままできます。
 再帰を用いた正規表現の説明書:PHP: 再帰的パターン – Manual

著者:杉浦

GNSS受信機が何を出力しているかGUIで見るu-center

 u-centerはGNSS受信機のメーカであるu-bloxが公開しているフリーソフトです。このソフトはGUIが便利で多機能です。受信機の位置、受け取った衛星の状態をはじめとして様々な情報を確認できます。機能の一つであるパケットコンソール、メッセージビューからはGNSS受信機がどの様な情報を出力しているかを見ることが出来ます。
 パケットコンソールは信号のプロトコルとその信号についての簡単なメッセージを見せてくれます。View->Packet Consoleから呼び出します。
 
 下図の例では、信号をファイルから読み込んで再生しています。NMEA規格とUBX規格のデータを出力しているとわかります。

 メッセージビューは直近の信号(メッセージ)に含まれる情報の意味を分かりやすく見せてくれます。View->Messages Viewから呼び出します。

 下図はGNRMCの表です。G*RMCの*は衛星の種類を示します。PならGPS、LならGLONASS、NならGNSSまとめて、といった具合です。RMCは時刻(UTC,Date)と位置情報(Lat:緯度,Lon:経度)と簡単な速度(SOG:対地速度)を表しています。

 この二つの画面でどのような信号が流れているのか大体わかります。

著者:杉浦

phpの型の比較表

 詳しく知りたい方はPHP: PHP 型の比較表 – Manual を読みましょう。
 phpは暗黙の型変換を行う言語です。これは一々明示的に型変換を行う手間を省く便利さを持ちながらも想定外の動作の原因にもなります。

if($a)

という条件文が

$a = 0

の時に偽と判定されるバグり方は定番らしいです。別言語で私もやりました。その様な曖昧な動作ですが仕様は一律で決められています。マニュアルで確認しましょう。
 下の表はどちらもPHP: PHP 型の比較表 – Manual からの引用です。上の表は直感的に様々な対応をしてくれています。数字==”数字”⇒TRUEなんかは特に便利です。下の表は誤解が生じない明確な形です。失敗がまずい時、誤解を招かないコードを書きたい時なにかに良いです。

== による緩やかな比較
TRUE FALSE 1 0 -1 “1” “0” “-1” NULL array() “php” “”
TRUE TRUE FALSE TRUE FALSE TRUE TRUE FALSE TRUE FALSE FALSE TRUE FALSE
FALSE FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE TRUE TRUE FALSE TRUE
1 TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
0 FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE TRUE FALSE TRUE TRUE
-1 TRUE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
“1” TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
“0” FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
“-1” TRUE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
NULL FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE TRUE TRUE FALSE TRUE
array() FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE
“php” TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE
“” FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE TRUE
=== による厳密な比較
TRUE FALSE 1 0 -1 “1” “0” “-1” NULL array() “php” “”
TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
1 FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
0 FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
-1 FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
“1” FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
“0” FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
“-1” FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
NULL FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE
array() FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE
“php” FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE
“” FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE
著者:杉浦

フローチャート等のダイアグラムを気軽に書けるdraw.io

 この記事を書いている時点のwikipediaにおいてダイアグラムは次の様に紹介されています。

ダイアグラム(diagram)とは、情報を2次元幾何学モデルで視覚化した象徴的表現である。3次元の2次元への投影による視覚化も含む。関数などのそれはグラフと呼ぶ。

 ざっくばらんに言えば、言葉にするより図にした方が分かりやすいものを図にする、ということです。この手の作図でとりあえずでよく使われそうなのがpower pointです。実際、簡単な図程度なら少しの手間で望んだ図を作ることが出来ます。しかし、複雑な図になるほど極端に手間が辛くなります。図と矢印とその連結が単調なせいで複雑なダイアグラムを描いた時の入り組み方が恐ろしいことになりやすいです。draw.ioはその辺りを配慮してくれています。すぐに便利だと思えた機能には多段に直角以外で曲がる矢印、連結箇所の多い図形、多数用意されたダイアグラム向けの図形がありました。
 基本draw.io上の作図状態はgoogle driveに保存されますが出力はローカルを始め多様な場所にできます。”ヘルプ->ダウンロードする”からオフライン用実行ファイルがダウンロードでき、”ヘルプ->オフライン”からローカルのみで読み書きができます。作図結果の出力はPNG、PDF、HTML、URLなどなどと様々です。英語に抵抗があっても、右上の地球マークから好きな言語を選ぶことが出来ます。もちろん日本語もあります。

 下図は過去の記事で描いたダイアグラムです。

 これはpower pointで描きました。計ってはいませんでしたがそれなりに時間がかかっていたはずです。この図をdraw.io上で再現した結果が次です。
 


 おおよそ7分ほどで描けました。ストレスフリーでさっくり描けて楽でした。