ガジェット通信

見たことのないものを見に行こう

【選択式問題】正規表現パズル2解答と解説☆言語不問

DATE:
  • ガジェット通信を≫

正規表現パズル2

本問題は、置換結果と置換文字列から推理して、検索の正規表現を選択肢から選ぶというものでした。

それでは以下、各問題とその解答を見ていきましょう。

問題のオープニング

あなたは、正規表現の女神「レギュ=ラー」の神殿にやって来ました。

この神殿では、女神の出す問題に正解すれば富を約束され、間違うと死を約束されます。

あなたは、歴戦のプログラマーとして、女神に「えくすぷれっしょん!」と、くしゃみをさせなければなりません。

この神殿では、以下のような式が提示されます。

文字列1

検索 置換

文字列2

この「検索」に当てはまる正規表現を、選択肢から選びます。置換は全置換です。

また、置換文字列に「$1」「$2」…がある場合は、丸括弧で記憶した値(数値番目)に置換します。

// 仮想コードのルール
. … 任意の1文字
* … 直前の文字を0回以上繰り返し
+ … 直前の文字を1回以上繰り返し
^ … 先頭
$ … 末尾
w … アンダーバーを含む英数字
d … 数字
… 次の特殊文字をエスケープ
[xyz] … xyzいずれかの文字
[^xyz] … xyz以外の文字
(x) … xを記憶
Aaa|Bbb … Aaa or Bbb
置換文字列の$1 $2…丸括弧で記憶した数値番目に置換
置換文字列の(空文字)…空の文字列を指す

問題1

// 問題
2016年2月22日

? $1/$2/$3

2016/2/22

// 選択肢
(d)+D(d)+D(d)+d
(d+).(d+).(d+).
([0-9])年([0-9])月([0-9])日

それでは各選択肢の正規表現を解説していきます。

選択肢1「(d)+D(d)+D(d)+d」→置換結果「6/2/2日」。

「d」は数字1文字、「D」は数字以外1文字です。そして「d+」は、数字1文字以上です。しかし「(d)+」のように括弧を付けると、記憶されるのは数字1文字だけになってしまいます。そのため「2016年2月22」のうち「6」「2」「2」が記憶され、「6/2/2日」のように、数字の1文字ずつしか、置換結果に表れません。

選択肢2「(d+).(d+).(d+).」→置換結果「2016/2/22」。

「(d+)」は数字1文字以上を記憶します。また「.」は任意の1文字なので、年月日の1文字に対応します。そのため「2016/2/22」のように、意図した置換結果になります。

選択肢3「([0-9])年([0-9])月([0-9])日」→置換結果「2016年2月22日」。

「[0-9]」は、数字1文字です。「+」などで繰り返しを指定していないために、複数の数字にはマッチしません。そのためマッチせず置換は行われません。

そのため答えは、2番目の選択肢の『(d+).(d+).(d+).』になります。

以下、ブラウザのコンソールで確認できるように、JavaScriptのコードを示します。

// 参考コード

// 変数
var src = “2016年2月22日”;
var rep = “$1/$2/$3″;
var res = “2016/2/22″;

// 問題
console.log(r = src.replace(/(d)+D(d)+D(d)+d/g, rep), r == res);
console.log(r = src.replace(/(d+).(d+).(d+)./g, rep), r == res);
console.log(r = src.replace(/([0-9])年([0-9])月([0-9])日/g, rep), r == res);

// 出力結果
6/2/2日 false
2016/2/22 true
2016年2月22日 false

問題2

// 問題
I and You.

? $2 and $1

You and I.

// 選択肢
1 and 2
(.+) and (.+)
(w+) w+ (w+)

それでは各選択肢の正規表現を解説していきます。

選択肢1「1 and 2」→置換結果「I and You.」。

「1」「2」の記号は、仮想コードのルールに記載がありません。そのため、マッチすることもありません。

選択肢2「(.+) and (.+)」→置換結果「You. and I」。

「.」は任意の1文字です。そのため「(.+)」は、英文字だけでなく「.」も含みます。つまり「You.」がマッチします。その結果、「You. and I」という、意図せぬ置換結果になります。

選択肢3「(w+) w+ (w+)」→置換結果「You and I.」。

「w」はアンダーバーを含む英数字です。そのため「w+」は、「You」「and」「I」にそれぞれ一致します。「(w+)」のように、丸括弧が付いている場所は「You」「I」の2ヶ所です。これらの文字列は、置換時の$1、$2に対応します。その結果「You and I.」と意図したとおりの置換結果になります。

そのため答えは、3番目の選択肢の『(w+) w+ (w+)』になります。

以下、ブラウザのコンソールで確認できるように、JavaScriptのコードを示します。

// 参考コード

// 変数
var src = “I and You.”;
var rep = “$2 and $1″;
var res = “You and I.”;

// 問題
console.log(r = src.replace(/1 and 2/g, rep), r == res);
console.log(r = src.replace(/(.+) and (.+)/g, rep), r == res);
console.log(r = src.replace(/(w+) w+ (w+)/g, rep), r == res);

// 出力結果
I and You. false
You. and I false
You and I. true

問題3

// 問題

http://abc.def/ghi/jkl/mno.html


? (空文字)

mno

// 選択肢
.+/|.[^.]+$
^.*m|.+
.+/(.+).html

それでは各選択肢の正規表現を解説していきます。

選択肢1「.+/|.[^.]+$」→置換結果「mno」。

「.+/」で、先頭から最後の「/」までに一致します。まず、この部分が削除されます。続いて「|」(OR)があるので、記号の右辺と左右のどちらでも一致します。「.[^.]+$」は、「.」から、「.」を含まない文字の連続で末尾までという正規表現です。この部分は拡張子部分に一致します。その結果「mno」のみが残されます。

選択肢2「^.*m|.+」→置換結果「l」。

「^.*m」は、先頭から最後の「m」までに一致します。続いて「|」(OR)があるので、記号の右辺と左右のどちらでも一致します。「.+」は1つ以上の「.」に一致します。ただし、最初の部分で「http://abc.def/ghi/jkl/mno.htm」まで削除されてしまうので、結果的に「l」しか残りません。

選択肢3「.+/(.+).html」→置換結果「」(空文字)。

「.+/」で、先頭から最後の「/」までに一致します。また「.html」は拡張子部分に一致します。そして、「(.+)」は任意の1文字が1文字以上ということで、この場合はファイル名に一致します。この正規表現は、「http://abc.def/ghi/jkl/mno.html」の全体に一致します。そして、置換文字列が空文字なので、全て削除されます(この正規表現は、もし置換文字列が「$1」ならば、「mno」を取り出せます)。

そのため答えは、1番目の選択肢の『.+/|.[^.]+$』になります。

以下、ブラウザのコンソールで確認できるように、JavaScriptのコードを示します。

// 参考コード

// 変数
var src = “http://abc.def/ghi/jkl/mno.html”;
var rep = “”;
var res = “mno”;

// 問題
console.log(r = src.replace(/.+/|.[^.]+$/g, rep), r == res);
console.log(r = src.replace(/^.*m|.+/g, rep), r == res);
console.log(r = src.replace(/.+/(.+).html/g, rep), r == res);

// 出力結果
mno true
l false
false

CodeIQ運営事務局より

柳井さん、ありがとうございました!
現在、柳井さんの最新問題が出題中です。
ぜひ挑戦してみてくださいね!

カテゴリー : デジタル・IT タグ :
CodeIQ MAGAZINEの記事一覧をみる ▶
  • 誤字を発見した方はこちらからご連絡ください。
  • ガジェット通信編集部への情報提供はこちらから
  • 記事内の筆者見解は明示のない限りガジェット通信を代表するものではありません。

TOP