著者アーカイブ 杉浦

著者:杉浦

インターネット上の技術仕様をまとめているRFC

 RFC(Request for Comments)はインターネット上の技術仕様をまとめているサイトです。2018/08/07におけるRFCのページには次の様にあります。

RFCs cover many aspects of computer networking, including protocols, procedures, programs, and concepts, as well as meeting notes, opinions, and sometimes humor.

 RFCは多岐にわたるインターネット技術の多くの側面をカバーしています。HTTPの様なプロトコルの定義に始まり、手続き、プログラム、コンセプト、議事録、ユーモアなどです。ユーモアにはタイトルだけで落ちているようなRFC1149 – 鳥類キャリアによる IP データグラムの伝送規格洗濯バサミ DHCP による IP アドレスの管理手法といったものがあります。
 最近、へぇ~となったのはメールアドレスの規格であるRFC 5321 – Simple Mail Transfer Protocolです。具体的な強制力はありませんが、大体これに従っています。注目するのは4.1.2節のCommand Argument Syntax、メールアドレスの構文です。メールアドレスといえば、@で前後を区切られるアドレスで@はメールアドレス中に一つだけとなんとなく思っている人が多いはずです。RFC 5321には次の様に記述されています。

   Mailbox        = Local-part "@" ( Domain / address-literal )

   Local-part     = Dot-string / Quoted-string
                  ; MAY be case-sensitive

...

   Quoted-string  = DQUOTE *QcontentSMTP DQUOTE
   
   QcontentSMTP   = qtextSMTP / quoted-pairSMTP

   quoted-pairSMTP  = %d92 %d32-126
                    ; i.e., backslash followed by any ASCII
                    ; graphic (including itself) or SPace

   qtextSMTP      = %d32-33 / %d35-91 / %d93-126
                  ; i.e., within a quoted string, any
                  ; ASCII graphic or space is permitted
                  ; without blackslash-quoting except
                  ; double-quote and the backslash itself.

 読み方は変数を当てはめていく感じです。

Mailbox = Local-part "@" ( Domain / address-literal )
Mailbox = (Dot-string / Quoted-string) "@" ( Domain / address-literal )
Mailbox = (Dot-string / DQUOTE *QcontentSMTP DQUOTE) "@" ( Domain / address-literal )
Mailbox = (Dot-string / DQUOTE *(qtextSMTP / quoted-pairSMTP) DQUOTE) "@" ( Domain / address-literal )
Mailbox = (Dot-string / DQUOTE *((%d32-33 / %d35-91 / %d93-126) / quoted-pairSMTP) DQUOTE) "@" ( Domain / address-literal )
 括弧の中の注目する部分だけ残して
Mailbox = DQUOTE *(%d32-33 / %d35-91 / %d93-126) DQUOTE "@" ( Domain / address-literal )

 %3aから%40までには広く使われる記号が入っており、@も含まれています。DQUOTE、つまり”で括ればこれらも使えるので”@@@@@”@gmail.comなんてアドレスもRFCに準拠するメールアドレスになります。もっとも、””で括ったメールアドレスはあまり一般的とはいえず、インターネット上の少なくない場所で弾かれます。小ネタでした。

著者:杉浦

頻繁に変わる一部分を抽出することによる関数化

 プログラミングを行う時、何を関数やクラスにすると楽ができるか、のちに使いやすくなるか、という判断のために抽出による判断ができます。抽出という言葉は抽出とは – 難読語辞典 Weblio辞書では次の様に載っています

ちゅう しゅつちう- [0] 【抽出】

( 名 ) スル

全体の中から、ある物を抜き出すこと。 「リストから条件を満たす物を-する」
固体または液体混合物溶媒加え混合物中の特定の成分溶媒中へ分離する操作。この操作後に得られる溶媒部分を抽出液という。溶媒抽出



 何らかの大きな問題を解く時、頻繁にある一部分のみが変わる同じような小さな問題を解くことになりやすいです。例えば問題が”Weblio辞書で数字の1から10までの意味を調べる”なら”Weblio辞書で数字の1の意味を調べる”,”Weblio辞書で数字の2の意味を調べる”,…です。これを更にブラウザ上の操作に分解すると”Weblio辞書を開く。”、”Weblio辞書で数字の1を検索バーに入力する。”、”検索ボタンを押す。”、”意味を読む。”になります。”Weblio辞書を開く”は最初の一度のみですが他を繰り返すだけで書き下されたコードは大変なことになります。


"Weblio辞書を開く。"
"Weblio辞書で数字の1を検索バーに入力する。"
"検索ボタンを押す。"
"意味を読む。"
"Weblio辞書で数字の2を検索バーに入力する。"
"検索ボタンを押す。"
"意味を読む。"
"Weblio辞書で数字の3を検索バーに入力する。"
"検索ボタンを押す。"
"意味を読む。"
"Weblio辞書で数字の4を検索バーに入力する。"
"検索ボタンを押す。"
"意味を読む。"
"Weblio辞書で数字の5を検索バーに入力する。"
"検索ボタンを押す。"
"意味を読む。"
"Weblio辞書で数字の6を検索バーに入力する。"
"検索ボタンを押す。"
"意味を読む。"
"Weblio辞書で数字の7を検索バーに入力する。"
"検索ボタンを押す。"
"意味を読む。"
"Weblio辞書で数字の8を検索バーに入力する。"
"検索ボタンを押す。"
"意味を読む。"
"Weblio辞書で数字の9を検索バーに入力する。"
"検索ボタンを押す。"
"意味を読む。"
"Weblio辞書で数字の10を検索バーに入力する。"
"検索ボタンを押す。"
"意味を読む。"

 読み難いです。分解した小さな問題の頻繁に変わる1~10の部分のみを抽出して、”Weblio辞書で数字の$nの意味を調べる”という関数に適宜挿入するコードは次の様になります。

function look_up_number_in_weblio($n){
	"Weblio辞書で数字の$nを検索バーに入力する。"
	"検索ボタンを押す。"
	"意味を読む。"
}
"Weblio辞書を開く。"
look_up_number_in_weblio(1);
look_up_number_in_weblio(2);
look_up_number_in_weblio(3);
look_up_number_in_weblio(4);
look_up_number_in_weblio(5);
look_up_number_in_weblio(6);
look_up_number_in_weblio(7);
look_up_number_in_weblio(8);
look_up_number_in_weblio(9);
look_up_number_in_weblio(10);

 さっくり全部読めるようになりました。

著者:杉浦

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:対地速度)を表しています。

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