ガジェット通信 GetNews

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

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

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

正規表現パズル

本問題は、正しい置換を行う正規表現を選ぶという内容でした。

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

問題のオープニング

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

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

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

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

文字列1

検索 置換

文字列2

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

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

// 問題中に出てくる正規表現の記号
. … 任意の1文字
* … 直前の文字を0回以上繰り返し
+ … 直前の文字を1回以上繰り返し
^ … 先頭
$ … 末尾
w … アンダーバーを含む英数字
d … 数字
… 次の特殊文字をエスケープ
[xyz] … xyzいずれかの文字
[^xyz] … xyz以外の文字
x{2} … 2文字のx
x{2,} … 2文字以上のx
x{2,4} … 2文字以上、4文字以下のx
(x) … xを記憶
x(?=y) … xにyが続く場合のx

問題1

// 問題
dog cat rat bat

? animal

animal animal animal animal

// 選択肢
.*
w+
.{3}

「dog」「cat」「rat」「bat」という単語を、全て「animal」に置換します。そのため、「dog」「cat」「rat」「bat」に一致して「 (半角スペース)」に一致しない正規表現を選ぶと正解になります。

各選択肢の置換結果は、以下になります。

選択肢1:『animalanimal』
選択肢2:『animal animal animal animal』
選択肢3:『animalanimalanimalanimalanimal』

選択肢1の「.*」は、「任意の文字0文字以上」なので、「dog cat rat bat」と「(空文字)」に一致して、「animalanimal」と置換されます。

選択肢2の「w+」は、「英数字1文字以上」なので、「dog」「cat」「rat」「bat」に一致して、「animal animal animal animal」と置換されます。

選択肢3の「.{3}」は、「任意の文字3文字」なので、「dog」「 ca」「t r」「at 」「bat」に一致して、「animalanimalanimalanimalanimal」と置換されます。

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

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

// 参考コード

// 変数
var s1 = “dog cat rat bat”;
var s2 = “animal”;
var s3 = “animal animal animal animal”;

// 選択肢
console.log(“選択肢1:”, r = s1.replace(/.*/g, s2), “/”, r == s3);
console.log(“選択肢2:”, r = s1.replace(/w+/g, s2), “/”, r == s3);
console.log(“選択肢3:”, r = s1.replace(/.{3}/g, s2), “/”, r == s3);

// 出力結果
選択肢1: animalanimal / false
選択肢2: animal animal animal animal / true
選択肢3: animalanimalanimalanimalanimal / false

問題2

// 問題
(^o^)(T_T)(^o^)(T_T)(^o^)(T_T)

? $2$1

(T_T)(^o^)(T_T)(^o^)(T_T)(^o^)

// 選択肢
(…)(…)
([(^oT_)]+)([(^oT_)]+)
([^)]+))([^)]+))

「(^o^)(T_T)(^o^)(T_T)(^o^)(T_T)」という文字列を、「(T_T)(^o^)(T_T)(^o^)(T_T)(^o^)」に置換しています。「(^o^)」と「(T_T)」を単語と見なして、この2つの単語を入れ替えることになります。

各選択肢の置換結果は、以下になります。

選択肢1:『^)((^o)(^T_T(T_o^)^o^T)(_T))(T』
選択肢2:『)(^o^)(T_T)(^o^)(T_T)(^o^)(T_T』
選択肢3:『(T_T)(^o^)(T_T)(^o^)(T_T)(^o^)』

選択肢1の「(…)(…)」は、3文字ごとにグループ化を行い、入れ替えています。「(^o^)」や「(T_T)」は5文字です。そのため、意図した置換にはなりません。

選択肢2の「([(^oT_)]+)([(^oT_)]+)」は、最初のグループも、2番目のグループも、文字列中の全ての文字に一致します。そのため、「(^o^)(T_T)(^o^)(T_T)(^o^)(T_T」「)」のようにグループ化されて、入れ替えられます。

選択肢3の「([^)]+))([^)]+))」は、「)」までを1グループとして見なします。この正規表現は「(^o^)」と「(T_T)」に一致するので、入れ替えることができます。

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

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

// 参考コード

// 変数
var s1 = “(^o^)(T_T)(^o^)(T_T)(^o^)(T_T)”;
var s2 = “$2$1”;
var s3 = “(T_T)(^o^)(T_T)(^o^)(T_T)(^o^)”;

// 選択肢
console.log(“選択肢1:”, r = s1.replace(/(…)(…)/g, s2), “/”, r == s3);
console.log(“選択肢2:”, r = s1.replace(/([(^oT_)]+)([(^oT_)]+)/g, s2), “/”, r == s3);
console.log(“選択肢3:”, r = s1.replace(/([^)]+))([^)]+))/g, s2), “/”, r == s3);

// 出力結果
選択肢1: ^)((^o)(^T_T(T_o^)^o^T)(_T))(T / false
選択肢2: )(^o^)(T_T)(^o^)(T_T)(^o^)(T_T / false
選択肢3: (T_T)(^o^)(T_T)(^o^)(T_T)(^o^) / true

問題3

// 問題
12345678

? $1,

12,345,678

// 選択肢
(d)(?=d{3} +$)
(d)(?=(d{3})+)$
(d)(?=(d{3})+$)

「12345678」という文字列を、「12,345,678」に置換しています。

各選択肢の置換結果は、以下になります。

選択肢1:『12345678』
選択肢2:『12345678』
選択肢3:『12,345,678』

この問題では、正解の選択肢3の正規表現が、どのように組み立てられているのかを、見ていきましょう。

まずは「(d{3})」です。この部分は、「数字が3つ」という意味になります。

次に「(d{3})+$」で、「数字が3つ」を繰り返した直後が「末尾」という意味になります。

さらに「(d)(?=(d{3})+$)」で、これまで組み立てた正規表現の前に「数字」があるという意味になります。つまり、「数字3つ1回以上+末尾」があとに続く「数字」が一致対象になります。

そのため、「12345678」のうち、「1(2)34(5)678)」の丸括弧の部分が一致して、グループ化されます。

そのため答えは、3番目の選択肢の『(d)(?=(d{3})+$)』になります。

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

// 参考コード

// 変数
var s1 = “12345678”;
var s2 = “$1,”;
var s3 = “12,345,678”;

// 選択肢
console.log(“選択肢1:”, r = s1.replace(/(d)(?=d{3} +$)/g, s2), “/”, r == s3);
console.log(“選択肢2:”, r = s1.replace(/(d)(?=(d{3})+)$/g, s2), “/”, r == s3);
console.log(“選択肢3:”, r = s1.replace(/(d)(?=(d{3})+$)/g, s2), “/”, r == s3);

// 出力結果
選択肢1: 12345678 / false
選択肢2: 12345678 / false
選択肢3: 12,345,678 / true

また、一致部分を目視で確認するための、JavaScriptのコードを示します。

// 参考コード
var s1 = “12345678”;
var s2 = “($1)”;
console.log(s1.replace(/(d)(?=(d{3})+$)/g, s2));

// 出力結果
1(2)34(5)678

CodeIQ運営事務局より

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

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